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
)
300 if (!isValidVarNameStart(Str
[I
++]))
301 return ErrorDiagnostic::get(SM
, Str
, "invalid variable name");
303 for (size_t E
= Str
.size(); I
!= E
; ++I
)
304 // Variable names are composed of alphanumeric characters and underscores.
305 if (Str
[I
] != '_' && !isAlnum(Str
[I
]))
308 StringRef Name
= Str
.take_front(I
);
310 return VariableProperties
{Name
, IsPseudo
};
313 // StringRef holding all characters considered as horizontal whitespaces by
314 // FileCheck input canonicalization.
315 constexpr StringLiteral SpaceChars
= " \t";
317 // Parsing helper function that strips the first character in S and returns it.
318 static char popFront(StringRef
&S
) {
324 char OverflowError::ID
= 0;
325 char UndefVarError::ID
= 0;
326 char ErrorDiagnostic::ID
= 0;
327 char NotFoundError::ID
= 0;
328 char ErrorReported::ID
= 0;
330 Expected
<NumericVariable
*> Pattern::parseNumericVariableDefinition(
331 StringRef
&Expr
, FileCheckPatternContext
*Context
,
332 std::optional
<size_t> LineNumber
, ExpressionFormat ImplicitFormat
,
333 const SourceMgr
&SM
) {
334 Expected
<VariableProperties
> ParseVarResult
= parseVariable(Expr
, SM
);
336 return ParseVarResult
.takeError();
337 StringRef Name
= ParseVarResult
->Name
;
339 if (ParseVarResult
->IsPseudo
)
340 return ErrorDiagnostic::get(
341 SM
, Name
, "definition of pseudo numeric variable unsupported");
343 // Detect collisions between string and numeric variables when the latter
344 // is created later than the former.
345 if (Context
->DefinedVariableTable
.contains(Name
))
346 return ErrorDiagnostic::get(
347 SM
, Name
, "string variable with name '" + Name
+ "' already exists");
349 Expr
= Expr
.ltrim(SpaceChars
);
351 return ErrorDiagnostic::get(
352 SM
, Expr
, "unexpected characters after numeric variable name");
354 NumericVariable
*DefinedNumericVariable
;
355 auto VarTableIter
= Context
->GlobalNumericVariableTable
.find(Name
);
356 if (VarTableIter
!= Context
->GlobalNumericVariableTable
.end()) {
357 DefinedNumericVariable
= VarTableIter
->second
;
358 if (DefinedNumericVariable
->getImplicitFormat() != ImplicitFormat
)
359 return ErrorDiagnostic::get(
360 SM
, Expr
, "format different from previous variable definition");
362 DefinedNumericVariable
=
363 Context
->makeNumericVariable(Name
, ImplicitFormat
, LineNumber
);
365 return DefinedNumericVariable
;
368 Expected
<std::unique_ptr
<NumericVariableUse
>> Pattern::parseNumericVariableUse(
369 StringRef Name
, bool IsPseudo
, std::optional
<size_t> LineNumber
,
370 FileCheckPatternContext
*Context
, const SourceMgr
&SM
) {
371 if (IsPseudo
&& !Name
.equals("@LINE"))
372 return ErrorDiagnostic::get(
373 SM
, Name
, "invalid pseudo numeric variable '" + Name
+ "'");
375 // Numeric variable definitions and uses are parsed in the order in which
376 // they appear in the CHECK patterns. For each definition, the pointer to the
377 // class instance of the corresponding numeric variable definition is stored
378 // in GlobalNumericVariableTable in parsePattern. Therefore, if the pointer
379 // we get below is null, it means no such variable was defined before. When
380 // that happens, we create a dummy variable so that parsing can continue. All
381 // uses of undefined variables, whether string or numeric, are then diagnosed
382 // in printNoMatch() after failing to match.
383 auto VarTableIter
= Context
->GlobalNumericVariableTable
.find(Name
);
384 NumericVariable
*NumericVariable
;
385 if (VarTableIter
!= Context
->GlobalNumericVariableTable
.end())
386 NumericVariable
= VarTableIter
->second
;
388 NumericVariable
= Context
->makeNumericVariable(
389 Name
, ExpressionFormat(ExpressionFormat::Kind::Unsigned
));
390 Context
->GlobalNumericVariableTable
[Name
] = NumericVariable
;
393 std::optional
<size_t> DefLineNumber
= NumericVariable
->getDefLineNumber();
394 if (DefLineNumber
&& LineNumber
&& *DefLineNumber
== *LineNumber
)
395 return ErrorDiagnostic::get(
397 "numeric variable '" + Name
+
398 "' defined earlier in the same CHECK directive");
400 return std::make_unique
<NumericVariableUse
>(Name
, NumericVariable
);
403 Expected
<std::unique_ptr
<ExpressionAST
>> Pattern::parseNumericOperand(
404 StringRef
&Expr
, AllowedOperand AO
, bool MaybeInvalidConstraint
,
405 std::optional
<size_t> LineNumber
, FileCheckPatternContext
*Context
,
406 const SourceMgr
&SM
) {
407 if (Expr
.startswith("(")) {
408 if (AO
!= AllowedOperand::Any
)
409 return ErrorDiagnostic::get(
410 SM
, Expr
, "parenthesized expression not permitted here");
411 return parseParenExpr(Expr
, LineNumber
, Context
, SM
);
414 if (AO
== AllowedOperand::LineVar
|| AO
== AllowedOperand::Any
) {
415 // Try to parse as a numeric variable use.
416 Expected
<Pattern::VariableProperties
> ParseVarResult
=
417 parseVariable(Expr
, SM
);
418 if (ParseVarResult
) {
419 // Try to parse a function call.
420 if (Expr
.ltrim(SpaceChars
).startswith("(")) {
421 if (AO
!= AllowedOperand::Any
)
422 return ErrorDiagnostic::get(SM
, ParseVarResult
->Name
,
423 "unexpected function call");
425 return parseCallExpr(Expr
, ParseVarResult
->Name
, LineNumber
, Context
,
429 return parseNumericVariableUse(ParseVarResult
->Name
,
430 ParseVarResult
->IsPseudo
, LineNumber
,
434 if (AO
== AllowedOperand::LineVar
)
435 return ParseVarResult
.takeError();
436 // Ignore the error and retry parsing as a literal.
437 consumeError(ParseVarResult
.takeError());
440 // Otherwise, parse it as a literal.
442 StringRef SaveExpr
= Expr
;
443 bool Negative
= Expr
.consume_front("-");
444 if (!Expr
.consumeInteger((AO
== AllowedOperand::LegacyLiteral
) ? 10 : 0,
446 LiteralValue
= toSigned(LiteralValue
, Negative
);
447 return std::make_unique
<ExpressionLiteral
>(SaveExpr
.drop_back(Expr
.size()),
450 return ErrorDiagnostic::get(
453 (MaybeInvalidConstraint
? "matching constraint or " : "") +
457 Expected
<std::unique_ptr
<ExpressionAST
>>
458 Pattern::parseParenExpr(StringRef
&Expr
, std::optional
<size_t> LineNumber
,
459 FileCheckPatternContext
*Context
, const SourceMgr
&SM
) {
460 Expr
= Expr
.ltrim(SpaceChars
);
461 assert(Expr
.startswith("("));
463 // Parse right operand.
464 Expr
.consume_front("(");
465 Expr
= Expr
.ltrim(SpaceChars
);
467 return ErrorDiagnostic::get(SM
, Expr
, "missing operand in expression");
469 // Note: parseNumericOperand handles nested opening parentheses.
470 Expected
<std::unique_ptr
<ExpressionAST
>> SubExprResult
= parseNumericOperand(
471 Expr
, AllowedOperand::Any
, /*MaybeInvalidConstraint=*/false, LineNumber
,
473 Expr
= Expr
.ltrim(SpaceChars
);
474 while (SubExprResult
&& !Expr
.empty() && !Expr
.startswith(")")) {
475 StringRef OrigExpr
= Expr
;
476 SubExprResult
= parseBinop(OrigExpr
, Expr
, std::move(*SubExprResult
), false,
477 LineNumber
, Context
, SM
);
478 Expr
= Expr
.ltrim(SpaceChars
);
481 return SubExprResult
;
483 if (!Expr
.consume_front(")")) {
484 return ErrorDiagnostic::get(SM
, Expr
,
485 "missing ')' at end of nested expression");
487 return SubExprResult
;
490 Expected
<std::unique_ptr
<ExpressionAST
>>
491 Pattern::parseBinop(StringRef Expr
, StringRef
&RemainingExpr
,
492 std::unique_ptr
<ExpressionAST
> LeftOp
,
493 bool IsLegacyLineExpr
, std::optional
<size_t> LineNumber
,
494 FileCheckPatternContext
*Context
, const SourceMgr
&SM
) {
495 RemainingExpr
= RemainingExpr
.ltrim(SpaceChars
);
496 if (RemainingExpr
.empty())
497 return std::move(LeftOp
);
499 // Check if this is a supported operation and select a function to perform
501 SMLoc OpLoc
= SMLoc::getFromPointer(RemainingExpr
.data());
502 char Operator
= popFront(RemainingExpr
);
503 binop_eval_t EvalBinop
;
512 return ErrorDiagnostic::get(
513 SM
, OpLoc
, Twine("unsupported operation '") + Twine(Operator
) + "'");
516 // Parse right operand.
517 RemainingExpr
= RemainingExpr
.ltrim(SpaceChars
);
518 if (RemainingExpr
.empty())
519 return ErrorDiagnostic::get(SM
, RemainingExpr
,
520 "missing operand in expression");
521 // The second operand in a legacy @LINE expression is always a literal.
523 IsLegacyLineExpr
? AllowedOperand::LegacyLiteral
: AllowedOperand::Any
;
524 Expected
<std::unique_ptr
<ExpressionAST
>> RightOpResult
=
525 parseNumericOperand(RemainingExpr
, AO
, /*MaybeInvalidConstraint=*/false,
526 LineNumber
, Context
, SM
);
528 return RightOpResult
;
530 Expr
= Expr
.drop_back(RemainingExpr
.size());
531 return std::make_unique
<BinaryOperation
>(Expr
, EvalBinop
, std::move(LeftOp
),
532 std::move(*RightOpResult
));
535 Expected
<std::unique_ptr
<ExpressionAST
>>
536 Pattern::parseCallExpr(StringRef
&Expr
, StringRef FuncName
,
537 std::optional
<size_t> LineNumber
,
538 FileCheckPatternContext
*Context
, const SourceMgr
&SM
) {
539 Expr
= Expr
.ltrim(SpaceChars
);
540 assert(Expr
.startswith("("));
542 auto OptFunc
= StringSwitch
<binop_eval_t
>(FuncName
)
543 .Case("add", exprAdd
)
544 .Case("div", exprDiv
)
545 .Case("max", exprMax
)
546 .Case("min", exprMin
)
547 .Case("mul", exprMul
)
548 .Case("sub", exprSub
)
552 return ErrorDiagnostic::get(
553 SM
, FuncName
, Twine("call to undefined function '") + FuncName
+ "'");
555 Expr
.consume_front("(");
556 Expr
= Expr
.ltrim(SpaceChars
);
558 // Parse call arguments, which are comma separated.
559 SmallVector
<std::unique_ptr
<ExpressionAST
>, 4> Args
;
560 while (!Expr
.empty() && !Expr
.startswith(")")) {
561 if (Expr
.startswith(","))
562 return ErrorDiagnostic::get(SM
, Expr
, "missing argument");
564 // Parse the argument, which is an arbitary expression.
565 StringRef OuterBinOpExpr
= Expr
;
566 Expected
<std::unique_ptr
<ExpressionAST
>> Arg
= parseNumericOperand(
567 Expr
, AllowedOperand::Any
, /*MaybeInvalidConstraint=*/false, LineNumber
,
569 while (Arg
&& !Expr
.empty()) {
570 Expr
= Expr
.ltrim(SpaceChars
);
571 // Have we reached an argument terminator?
572 if (Expr
.startswith(",") || Expr
.startswith(")"))
575 // Arg = Arg <op> <expr>
576 Arg
= parseBinop(OuterBinOpExpr
, Expr
, std::move(*Arg
), false, LineNumber
,
580 // Prefer an expression error over a generic invalid argument message.
582 return Arg
.takeError();
583 Args
.push_back(std::move(*Arg
));
585 // Have we parsed all available arguments?
586 Expr
= Expr
.ltrim(SpaceChars
);
587 if (!Expr
.consume_front(","))
590 Expr
= Expr
.ltrim(SpaceChars
);
591 if (Expr
.startswith(")"))
592 return ErrorDiagnostic::get(SM
, Expr
, "missing argument");
595 if (!Expr
.consume_front(")"))
596 return ErrorDiagnostic::get(SM
, Expr
,
597 "missing ')' at end of call expression");
599 const unsigned NumArgs
= Args
.size();
601 return std::make_unique
<BinaryOperation
>(Expr
, *OptFunc
, std::move(Args
[0]),
604 // TODO: Support more than binop_eval_t.
605 return ErrorDiagnostic::get(SM
, FuncName
,
606 Twine("function '") + FuncName
+
607 Twine("' takes 2 arguments but ") +
608 Twine(NumArgs
) + " given");
611 Expected
<std::unique_ptr
<Expression
>> Pattern::parseNumericSubstitutionBlock(
612 StringRef Expr
, std::optional
<NumericVariable
*> &DefinedNumericVariable
,
613 bool IsLegacyLineExpr
, std::optional
<size_t> LineNumber
,
614 FileCheckPatternContext
*Context
, const SourceMgr
&SM
) {
615 std::unique_ptr
<ExpressionAST
> ExpressionASTPointer
= nullptr;
616 StringRef DefExpr
= StringRef();
617 DefinedNumericVariable
= std::nullopt
;
618 ExpressionFormat ExplicitFormat
= ExpressionFormat();
619 unsigned Precision
= 0;
621 // Parse format specifier (NOTE: ',' is also an argument seperator).
622 size_t FormatSpecEnd
= Expr
.find(',');
623 size_t FunctionStart
= Expr
.find('(');
624 if (FormatSpecEnd
!= StringRef::npos
&& FormatSpecEnd
< FunctionStart
) {
625 StringRef FormatExpr
= Expr
.take_front(FormatSpecEnd
);
626 Expr
= Expr
.drop_front(FormatSpecEnd
+ 1);
627 FormatExpr
= FormatExpr
.trim(SpaceChars
);
628 if (!FormatExpr
.consume_front("%"))
629 return ErrorDiagnostic::get(
631 "invalid matching format specification in expression");
633 // Parse alternate form flag.
634 SMLoc AlternateFormFlagLoc
= SMLoc::getFromPointer(FormatExpr
.data());
635 bool AlternateForm
= FormatExpr
.consume_front("#");
638 if (FormatExpr
.consume_front(".")) {
639 if (FormatExpr
.consumeInteger(10, Precision
))
640 return ErrorDiagnostic::get(SM
, FormatExpr
,
641 "invalid precision in format specifier");
644 if (!FormatExpr
.empty()) {
645 // Check for unknown matching format specifier and set matching format in
646 // class instance representing this expression.
647 SMLoc FmtLoc
= SMLoc::getFromPointer(FormatExpr
.data());
648 switch (popFront(FormatExpr
)) {
651 ExpressionFormat(ExpressionFormat::Kind::Unsigned
, Precision
);
655 ExpressionFormat(ExpressionFormat::Kind::Signed
, Precision
);
658 ExplicitFormat
= ExpressionFormat(ExpressionFormat::Kind::HexLower
,
659 Precision
, AlternateForm
);
662 ExplicitFormat
= ExpressionFormat(ExpressionFormat::Kind::HexUpper
,
663 Precision
, AlternateForm
);
666 return ErrorDiagnostic::get(SM
, FmtLoc
,
667 "invalid format specifier in expression");
671 if (AlternateForm
&& ExplicitFormat
!= ExpressionFormat::Kind::HexLower
&&
672 ExplicitFormat
!= ExpressionFormat::Kind::HexUpper
)
673 return ErrorDiagnostic::get(
674 SM
, AlternateFormFlagLoc
,
675 "alternate form only supported for hex values");
677 FormatExpr
= FormatExpr
.ltrim(SpaceChars
);
678 if (!FormatExpr
.empty())
679 return ErrorDiagnostic::get(
681 "invalid matching format specification in expression");
684 // Save variable definition expression if any.
685 size_t DefEnd
= Expr
.find(':');
686 if (DefEnd
!= StringRef::npos
) {
687 DefExpr
= Expr
.substr(0, DefEnd
);
688 Expr
= Expr
.substr(DefEnd
+ 1);
691 // Parse matching constraint.
692 Expr
= Expr
.ltrim(SpaceChars
);
693 bool HasParsedValidConstraint
= false;
694 if (Expr
.consume_front("=="))
695 HasParsedValidConstraint
= true;
697 // Parse the expression itself.
698 Expr
= Expr
.ltrim(SpaceChars
);
700 if (HasParsedValidConstraint
)
701 return ErrorDiagnostic::get(
702 SM
, Expr
, "empty numeric expression should not have a constraint");
704 Expr
= Expr
.rtrim(SpaceChars
);
705 StringRef OuterBinOpExpr
= Expr
;
706 // The first operand in a legacy @LINE expression is always the @LINE
709 IsLegacyLineExpr
? AllowedOperand::LineVar
: AllowedOperand::Any
;
710 Expected
<std::unique_ptr
<ExpressionAST
>> ParseResult
= parseNumericOperand(
711 Expr
, AO
, !HasParsedValidConstraint
, LineNumber
, Context
, SM
);
712 while (ParseResult
&& !Expr
.empty()) {
713 ParseResult
= parseBinop(OuterBinOpExpr
, Expr
, std::move(*ParseResult
),
714 IsLegacyLineExpr
, LineNumber
, Context
, SM
);
715 // Legacy @LINE expressions only allow 2 operands.
716 if (ParseResult
&& IsLegacyLineExpr
&& !Expr
.empty())
717 return ErrorDiagnostic::get(
719 "unexpected characters at end of expression '" + Expr
+ "'");
722 return ParseResult
.takeError();
723 ExpressionASTPointer
= std::move(*ParseResult
);
726 // Select format of the expression, i.e. (i) its explicit format, if any,
727 // otherwise (ii) its implicit format, if any, otherwise (iii) the default
728 // format (unsigned). Error out in case of conflicting implicit format
729 // without explicit format.
730 ExpressionFormat Format
;
732 Format
= ExplicitFormat
;
733 else if (ExpressionASTPointer
) {
734 Expected
<ExpressionFormat
> ImplicitFormat
=
735 ExpressionASTPointer
->getImplicitFormat(SM
);
737 return ImplicitFormat
.takeError();
738 Format
= *ImplicitFormat
;
741 Format
= ExpressionFormat(ExpressionFormat::Kind::Unsigned
, Precision
);
743 std::unique_ptr
<Expression
> ExpressionPointer
=
744 std::make_unique
<Expression
>(std::move(ExpressionASTPointer
), Format
);
746 // Parse the numeric variable definition.
747 if (DefEnd
!= StringRef::npos
) {
748 DefExpr
= DefExpr
.ltrim(SpaceChars
);
749 Expected
<NumericVariable
*> ParseResult
= parseNumericVariableDefinition(
750 DefExpr
, Context
, LineNumber
, ExpressionPointer
->getFormat(), SM
);
753 return ParseResult
.takeError();
754 DefinedNumericVariable
= *ParseResult
;
757 return std::move(ExpressionPointer
);
760 bool Pattern::parsePattern(StringRef PatternStr
, StringRef Prefix
,
761 SourceMgr
&SM
, const FileCheckRequest
&Req
) {
762 bool MatchFullLinesHere
= Req
.MatchFullLines
&& CheckTy
!= Check::CheckNot
;
763 IgnoreCase
= Req
.IgnoreCase
;
765 PatternLoc
= SMLoc::getFromPointer(PatternStr
.data());
767 if (!(Req
.NoCanonicalizeWhiteSpace
&& Req
.MatchFullLines
))
768 // Ignore trailing whitespace.
769 while (!PatternStr
.empty() &&
770 (PatternStr
.back() == ' ' || PatternStr
.back() == '\t'))
771 PatternStr
= PatternStr
.substr(0, PatternStr
.size() - 1);
773 // Check that there is something on the line.
774 if (PatternStr
.empty() && CheckTy
!= Check::CheckEmpty
) {
775 SM
.PrintMessage(PatternLoc
, SourceMgr::DK_Error
,
776 "found empty check string with prefix '" + Prefix
+ ":'");
780 if (!PatternStr
.empty() && CheckTy
== Check::CheckEmpty
) {
782 PatternLoc
, SourceMgr::DK_Error
,
783 "found non-empty check string for empty check with prefix '" + Prefix
+
788 if (CheckTy
== Check::CheckEmpty
) {
793 // If literal check, set fixed string.
794 if (CheckTy
.isLiteralMatch()) {
795 FixedStr
= PatternStr
;
799 // Check to see if this is a fixed string, or if it has regex pieces.
800 if (!MatchFullLinesHere
&&
801 (PatternStr
.size() < 2 ||
802 (!PatternStr
.contains("{{") && !PatternStr
.contains("[[")))) {
803 FixedStr
= PatternStr
;
807 if (MatchFullLinesHere
) {
809 if (!Req
.NoCanonicalizeWhiteSpace
)
813 // Paren value #0 is for the fully matched string. Any new parenthesized
814 // values add from there.
815 unsigned CurParen
= 1;
817 // Otherwise, there is at least one regex piece. Build up the regex pattern
818 // by escaping scary characters in fixed strings, building up one big regex.
819 while (!PatternStr
.empty()) {
821 if (PatternStr
.startswith("{{")) {
822 // This is the start of a regex match. Scan for the }}.
823 size_t End
= PatternStr
.find("}}");
824 if (End
== StringRef::npos
) {
825 SM
.PrintMessage(SMLoc::getFromPointer(PatternStr
.data()),
827 "found start of regex string with no end '}}'");
831 // Enclose {{}} patterns in parens just like [[]] even though we're not
832 // capturing the result for any purpose. This is required in case the
833 // expression contains an alternation like: CHECK: abc{{x|z}}def. We
834 // want this to turn into: "abc(x|z)def" not "abcx|zdef".
838 if (AddRegExToRegEx(PatternStr
.substr(2, End
- 2), CurParen
, SM
))
842 PatternStr
= PatternStr
.substr(End
+ 2);
846 // String and numeric substitution blocks. Pattern substitution blocks come
847 // in two forms: [[foo:.*]] and [[foo]]. The former matches .* (or some
848 // other regex) and assigns it to the string variable 'foo'. The latter
849 // substitutes foo's value. Numeric substitution blocks recognize the same
850 // form as string ones, but start with a '#' sign after the double
851 // brackets. They also accept a combined form which sets a numeric variable
852 // to the evaluation of an expression. Both string and numeric variable
853 // names must satisfy the regular expression "[a-zA-Z_][0-9a-zA-Z_]*" to be
854 // valid, as this helps catch some common errors. If there are extra '['s
855 // before the "[[", treat them literally.
856 if (PatternStr
.startswith("[[") && !PatternStr
.startswith("[[[")) {
857 StringRef UnparsedPatternStr
= PatternStr
.substr(2);
858 // Find the closing bracket pair ending the match. End is going to be an
859 // offset relative to the beginning of the match string.
860 size_t End
= FindRegexVarEnd(UnparsedPatternStr
, SM
);
861 StringRef MatchStr
= UnparsedPatternStr
.substr(0, End
);
862 bool IsNumBlock
= MatchStr
.consume_front("#");
864 if (End
== StringRef::npos
) {
865 SM
.PrintMessage(SMLoc::getFromPointer(PatternStr
.data()),
867 "Invalid substitution block, no ]] found");
870 // Strip the substitution block we are parsing. End points to the start
871 // of the "]]" closing the expression so account for it in computing the
872 // index of the first unparsed character.
873 PatternStr
= UnparsedPatternStr
.substr(End
+ 2);
875 bool IsDefinition
= false;
876 bool SubstNeeded
= false;
877 // Whether the substitution block is a legacy use of @LINE with string
878 // substitution block syntax.
879 bool IsLegacyLineExpr
= false;
882 StringRef MatchRegexp
;
883 std::string WildcardRegexp
;
884 size_t SubstInsertIdx
= RegExStr
.size();
886 // Parse string variable or legacy @LINE expression.
888 size_t VarEndIdx
= MatchStr
.find(':');
889 size_t SpacePos
= MatchStr
.substr(0, VarEndIdx
).find_first_of(" \t");
890 if (SpacePos
!= StringRef::npos
) {
891 SM
.PrintMessage(SMLoc::getFromPointer(MatchStr
.data() + SpacePos
),
892 SourceMgr::DK_Error
, "unexpected whitespace");
896 // Get the name (e.g. "foo") and verify it is well formed.
897 StringRef OrigMatchStr
= MatchStr
;
898 Expected
<Pattern::VariableProperties
> ParseVarResult
=
899 parseVariable(MatchStr
, SM
);
900 if (!ParseVarResult
) {
901 logAllUnhandledErrors(ParseVarResult
.takeError(), errs());
904 StringRef Name
= ParseVarResult
->Name
;
905 bool IsPseudo
= ParseVarResult
->IsPseudo
;
907 IsDefinition
= (VarEndIdx
!= StringRef::npos
);
908 SubstNeeded
= !IsDefinition
;
910 if ((IsPseudo
|| !MatchStr
.consume_front(":"))) {
911 SM
.PrintMessage(SMLoc::getFromPointer(Name
.data()),
913 "invalid name in string variable definition");
917 // Detect collisions between string and numeric variables when the
918 // former is created later than the latter.
919 if (Context
->GlobalNumericVariableTable
.contains(Name
)) {
921 SMLoc::getFromPointer(Name
.data()), SourceMgr::DK_Error
,
922 "numeric variable with name '" + Name
+ "' already exists");
926 MatchRegexp
= MatchStr
;
929 MatchStr
= OrigMatchStr
;
930 IsLegacyLineExpr
= IsNumBlock
= true;
932 if (!MatchStr
.empty()) {
933 SM
.PrintMessage(SMLoc::getFromPointer(Name
.data()),
935 "invalid name in string variable use");
943 // Parse numeric substitution block.
944 std::unique_ptr
<Expression
> ExpressionPointer
;
945 std::optional
<NumericVariable
*> DefinedNumericVariable
;
947 Expected
<std::unique_ptr
<Expression
>> ParseResult
=
948 parseNumericSubstitutionBlock(MatchStr
, DefinedNumericVariable
,
949 IsLegacyLineExpr
, LineNumber
, Context
,
952 logAllUnhandledErrors(ParseResult
.takeError(), errs());
955 ExpressionPointer
= std::move(*ParseResult
);
956 SubstNeeded
= ExpressionPointer
->getAST() != nullptr;
957 if (DefinedNumericVariable
) {
959 DefName
= (*DefinedNumericVariable
)->getName();
964 ExpressionFormat Format
= ExpressionPointer
->getFormat();
965 WildcardRegexp
= cantFail(Format
.getWildcardRegex());
966 MatchRegexp
= WildcardRegexp
;
970 // Handle variable definition: [[<def>:(...)]] and [[#(...)<def>:(...)]].
976 NumericVariableMatch NumericVariableDefinition
= {
977 *DefinedNumericVariable
, CurParen
};
978 NumericVariableDefs
[DefName
] = NumericVariableDefinition
;
979 // This store is done here rather than in match() to allow
980 // parseNumericVariableUse() to get the pointer to the class instance
981 // of the right variable definition corresponding to a given numeric
983 Context
->GlobalNumericVariableTable
[DefName
] =
984 *DefinedNumericVariable
;
986 VariableDefs
[DefName
] = CurParen
;
987 // Mark string variable as defined to detect collisions between
988 // string and numeric variables in parseNumericVariableUse() and
989 // defineCmdlineVariables() when the latter is created later than the
990 // former. We cannot reuse GlobalVariableTable for this by populating
991 // it with an empty string since we would then lose the ability to
992 // detect the use of an undefined variable in match().
993 Context
->DefinedVariableTable
[DefName
] = true;
999 if (!MatchRegexp
.empty() && AddRegExToRegEx(MatchRegexp
, CurParen
, SM
))
1005 // Handle substitutions: [[foo]] and [[#<foo expr>]].
1007 // Handle substitution of string variables that were defined earlier on
1008 // the same line by emitting a backreference. Expressions do not
1009 // support substituting a numeric variable defined on the same line.
1010 if (!IsNumBlock
&& VariableDefs
.find(SubstStr
) != VariableDefs
.end()) {
1011 unsigned CaptureParenGroup
= VariableDefs
[SubstStr
];
1012 if (CaptureParenGroup
< 1 || CaptureParenGroup
> 9) {
1013 SM
.PrintMessage(SMLoc::getFromPointer(SubstStr
.data()),
1014 SourceMgr::DK_Error
,
1015 "Can't back-reference more than 9 variables");
1018 AddBackrefToRegEx(CaptureParenGroup
);
1020 // Handle substitution of string variables ([[<var>]]) defined in
1021 // previous CHECK patterns, and substitution of expressions.
1022 Substitution
*Substitution
=
1024 ? Context
->makeNumericSubstitution(
1025 SubstStr
, std::move(ExpressionPointer
), SubstInsertIdx
)
1026 : Context
->makeStringSubstitution(SubstStr
, SubstInsertIdx
);
1027 Substitutions
.push_back(Substitution
);
1034 // Handle fixed string matches.
1035 // Find the end, which is the start of the next regex.
1036 size_t FixedMatchEnd
=
1037 std::min(PatternStr
.find("{{", 1), PatternStr
.find("[[", 1));
1038 RegExStr
+= Regex::escape(PatternStr
.substr(0, FixedMatchEnd
));
1039 PatternStr
= PatternStr
.substr(FixedMatchEnd
);
1042 if (MatchFullLinesHere
) {
1043 if (!Req
.NoCanonicalizeWhiteSpace
)
1051 bool Pattern::AddRegExToRegEx(StringRef RS
, unsigned &CurParen
, SourceMgr
&SM
) {
1054 if (!R
.isValid(Error
)) {
1055 SM
.PrintMessage(SMLoc::getFromPointer(RS
.data()), SourceMgr::DK_Error
,
1056 "invalid regex: " + Error
);
1060 RegExStr
+= RS
.str();
1061 CurParen
+= R
.getNumMatches();
1065 void Pattern::AddBackrefToRegEx(unsigned BackrefNum
) {
1066 assert(BackrefNum
>= 1 && BackrefNum
<= 9 && "Invalid backref number");
1067 std::string Backref
= std::string("\\") + std::string(1, '0' + BackrefNum
);
1068 RegExStr
+= Backref
;
1071 Pattern::MatchResult
Pattern::match(StringRef Buffer
,
1072 const SourceMgr
&SM
) const {
1073 // If this is the EOF pattern, match it immediately.
1074 if (CheckTy
== Check::CheckEOF
)
1075 return MatchResult(Buffer
.size(), 0, Error::success());
1077 // If this is a fixed string pattern, just match it now.
1078 if (!FixedStr
.empty()) {
1080 IgnoreCase
? Buffer
.find_insensitive(FixedStr
) : Buffer
.find(FixedStr
);
1081 if (Pos
== StringRef::npos
)
1082 return make_error
<NotFoundError
>();
1083 return MatchResult(Pos
, /*MatchLen=*/FixedStr
.size(), Error::success());
1088 // If there are substitutions, we need to create a temporary string with the
1090 StringRef RegExToMatch
= RegExStr
;
1092 if (!Substitutions
.empty()) {
1095 Context
->LineVariable
->setValue(
1096 APInt(sizeof(*LineNumber
) * 8, *LineNumber
));
1098 size_t InsertOffset
= 0;
1099 // Substitute all string variables and expressions whose values are only
1100 // now known. Use of string variables defined on the same line are handled
1101 // by back-references.
1102 Error Errs
= Error::success();
1103 for (const auto &Substitution
: Substitutions
) {
1104 // Substitute and check for failure (e.g. use of undefined variable).
1105 Expected
<std::string
> Value
= Substitution
->getResult();
1107 // Convert to an ErrorDiagnostic to get location information. This is
1108 // done here rather than printMatch/printNoMatch since now we know which
1109 // substitution block caused the overflow.
1110 Errs
= joinErrors(std::move(Errs
),
1113 [&](const OverflowError
&E
) {
1114 return ErrorDiagnostic::get(
1115 SM
, Substitution
->getFromString(),
1116 "unable to substitute variable or "
1117 "numeric expression: overflow error");
1119 [&SM
](const UndefVarError
&E
) {
1120 return ErrorDiagnostic::get(SM
, E
.getVarName(),
1126 // Plop it into the regex at the adjusted offset.
1127 TmpStr
.insert(TmpStr
.begin() + Substitution
->getIndex() + InsertOffset
,
1128 Value
->begin(), Value
->end());
1129 InsertOffset
+= Value
->size();
1132 return std::move(Errs
);
1134 // Match the newly constructed regex.
1135 RegExToMatch
= TmpStr
;
1138 SmallVector
<StringRef
, 4> MatchInfo
;
1139 unsigned int Flags
= Regex::Newline
;
1141 Flags
|= Regex::IgnoreCase
;
1142 if (!Regex(RegExToMatch
, Flags
).match(Buffer
, &MatchInfo
))
1143 return make_error
<NotFoundError
>();
1145 // Successful regex match.
1146 assert(!MatchInfo
.empty() && "Didn't get any match");
1147 StringRef FullMatch
= MatchInfo
[0];
1149 // If this defines any string variables, remember their values.
1150 for (const auto &VariableDef
: VariableDefs
) {
1151 assert(VariableDef
.second
< MatchInfo
.size() && "Internal paren error");
1152 Context
->GlobalVariableTable
[VariableDef
.first
] =
1153 MatchInfo
[VariableDef
.second
];
1156 // Like CHECK-NEXT, CHECK-EMPTY's match range is considered to start after
1157 // the required preceding newline, which is consumed by the pattern in the
1158 // case of CHECK-EMPTY but not CHECK-NEXT.
1159 size_t MatchStartSkip
= CheckTy
== Check::CheckEmpty
;
1161 TheMatch
.Pos
= FullMatch
.data() - Buffer
.data() + MatchStartSkip
;
1162 TheMatch
.Len
= FullMatch
.size() - MatchStartSkip
;
1164 // If this defines any numeric variables, remember their values.
1165 for (const auto &NumericVariableDef
: NumericVariableDefs
) {
1166 const NumericVariableMatch
&NumericVariableMatch
=
1167 NumericVariableDef
.getValue();
1168 unsigned CaptureParenGroup
= NumericVariableMatch
.CaptureParenGroup
;
1169 assert(CaptureParenGroup
< MatchInfo
.size() && "Internal paren error");
1170 NumericVariable
*DefinedNumericVariable
=
1171 NumericVariableMatch
.DefinedNumericVariable
;
1173 StringRef MatchedValue
= MatchInfo
[CaptureParenGroup
];
1174 ExpressionFormat Format
= DefinedNumericVariable
->getImplicitFormat();
1175 APInt Value
= Format
.valueFromStringRepr(MatchedValue
, SM
);
1176 DefinedNumericVariable
->setValue(Value
, MatchedValue
);
1179 return MatchResult(TheMatch
, Error::success());
1182 unsigned Pattern::computeMatchDistance(StringRef Buffer
) const {
1183 // Just compute the number of matching characters. For regular expressions, we
1184 // just compare against the regex itself and hope for the best.
1186 // FIXME: One easy improvement here is have the regex lib generate a single
1187 // example regular expression which matches, and use that as the example
1189 StringRef
ExampleString(FixedStr
);
1190 if (ExampleString
.empty())
1191 ExampleString
= RegExStr
;
1193 // Only compare up to the first line in the buffer, or the string size.
1194 StringRef BufferPrefix
= Buffer
.substr(0, ExampleString
.size());
1195 BufferPrefix
= BufferPrefix
.split('\n').first
;
1196 return BufferPrefix
.edit_distance(ExampleString
);
1199 void Pattern::printSubstitutions(const SourceMgr
&SM
, StringRef Buffer
,
1201 FileCheckDiag::MatchType MatchTy
,
1202 std::vector
<FileCheckDiag
> *Diags
) const {
1203 // Print what we know about substitutions.
1204 if (!Substitutions
.empty()) {
1205 for (const auto &Substitution
: Substitutions
) {
1206 SmallString
<256> Msg
;
1207 raw_svector_ostream
OS(Msg
);
1209 Expected
<std::string
> MatchedValue
= Substitution
->getResult();
1210 // Substitution failures are handled in printNoMatch().
1211 if (!MatchedValue
) {
1212 consumeError(MatchedValue
.takeError());
1217 OS
.write_escaped(Substitution
->getFromString()) << "\" equal to \"";
1218 OS
.write_escaped(*MatchedValue
) << "\"";
1220 // We report only the start of the match/search range to suggest we are
1221 // reporting the substitutions as set at the start of the match/search.
1222 // Indicating a non-zero-length range might instead seem to imply that the
1223 // substitution matches or was captured from exactly that range.
1225 Diags
->emplace_back(SM
, CheckTy
, getLoc(), MatchTy
,
1226 SMRange(Range
.Start
, Range
.Start
), OS
.str());
1228 SM
.PrintMessage(Range
.Start
, SourceMgr::DK_Note
, OS
.str());
1233 void Pattern::printVariableDefs(const SourceMgr
&SM
,
1234 FileCheckDiag::MatchType MatchTy
,
1235 std::vector
<FileCheckDiag
> *Diags
) const {
1236 if (VariableDefs
.empty() && NumericVariableDefs
.empty())
1238 // Build list of variable captures.
1243 SmallVector
<VarCapture
, 2> VarCaptures
;
1244 for (const auto &VariableDef
: VariableDefs
) {
1246 VC
.Name
= VariableDef
.first
;
1247 StringRef Value
= Context
->GlobalVariableTable
[VC
.Name
];
1248 SMLoc Start
= SMLoc::getFromPointer(Value
.data());
1249 SMLoc End
= SMLoc::getFromPointer(Value
.data() + Value
.size());
1250 VC
.Range
= SMRange(Start
, End
);
1251 VarCaptures
.push_back(VC
);
1253 for (const auto &VariableDef
: NumericVariableDefs
) {
1255 VC
.Name
= VariableDef
.getKey();
1256 std::optional
<StringRef
> StrValue
=
1257 VariableDef
.getValue().DefinedNumericVariable
->getStringValue();
1260 SMLoc Start
= SMLoc::getFromPointer(StrValue
->data());
1261 SMLoc End
= SMLoc::getFromPointer(StrValue
->data() + StrValue
->size());
1262 VC
.Range
= SMRange(Start
, End
);
1263 VarCaptures
.push_back(VC
);
1265 // Sort variable captures by the order in which they matched the input.
1266 // Ranges shouldn't be overlapping, so we can just compare the start.
1267 llvm::sort(VarCaptures
, [](const VarCapture
&A
, const VarCapture
&B
) {
1270 assert(A
.Range
.Start
!= B
.Range
.Start
&&
1271 "unexpected overlapping variable captures");
1272 return A
.Range
.Start
.getPointer() < B
.Range
.Start
.getPointer();
1274 // Create notes for the sorted captures.
1275 for (const VarCapture
&VC
: VarCaptures
) {
1276 SmallString
<256> Msg
;
1277 raw_svector_ostream
OS(Msg
);
1278 OS
<< "captured var \"" << VC
.Name
<< "\"";
1280 Diags
->emplace_back(SM
, CheckTy
, getLoc(), MatchTy
, VC
.Range
, OS
.str());
1282 SM
.PrintMessage(VC
.Range
.Start
, SourceMgr::DK_Note
, OS
.str(), VC
.Range
);
1286 static SMRange
ProcessMatchResult(FileCheckDiag::MatchType MatchTy
,
1287 const SourceMgr
&SM
, SMLoc Loc
,
1288 Check::FileCheckType CheckTy
,
1289 StringRef Buffer
, size_t Pos
, size_t Len
,
1290 std::vector
<FileCheckDiag
> *Diags
,
1291 bool AdjustPrevDiags
= false) {
1292 SMLoc Start
= SMLoc::getFromPointer(Buffer
.data() + Pos
);
1293 SMLoc End
= SMLoc::getFromPointer(Buffer
.data() + Pos
+ Len
);
1294 SMRange
Range(Start
, End
);
1296 if (AdjustPrevDiags
) {
1297 SMLoc CheckLoc
= Diags
->rbegin()->CheckLoc
;
1298 for (auto I
= Diags
->rbegin(), E
= Diags
->rend();
1299 I
!= E
&& I
->CheckLoc
== CheckLoc
; ++I
)
1300 I
->MatchTy
= MatchTy
;
1302 Diags
->emplace_back(SM
, CheckTy
, Loc
, MatchTy
, Range
);
1307 void Pattern::printFuzzyMatch(const SourceMgr
&SM
, StringRef Buffer
,
1308 std::vector
<FileCheckDiag
> *Diags
) const {
1309 // Attempt to find the closest/best fuzzy match. Usually an error happens
1310 // because some string in the output didn't exactly match. In these cases, we
1311 // would like to show the user a best guess at what "should have" matched, to
1312 // save them having to actually check the input manually.
1313 size_t NumLinesForward
= 0;
1314 size_t Best
= StringRef::npos
;
1315 double BestQuality
= 0;
1317 // Use an arbitrary 4k limit on how far we will search.
1318 for (size_t i
= 0, e
= std::min(size_t(4096), Buffer
.size()); i
!= e
; ++i
) {
1319 if (Buffer
[i
] == '\n')
1322 // Patterns have leading whitespace stripped, so skip whitespace when
1323 // looking for something which looks like a pattern.
1324 if (Buffer
[i
] == ' ' || Buffer
[i
] == '\t')
1327 // Compute the "quality" of this match as an arbitrary combination of the
1328 // match distance and the number of lines skipped to get to this match.
1329 unsigned Distance
= computeMatchDistance(Buffer
.substr(i
));
1330 double Quality
= Distance
+ (NumLinesForward
/ 100.);
1332 if (Quality
< BestQuality
|| Best
== StringRef::npos
) {
1334 BestQuality
= Quality
;
1338 // Print the "possible intended match here" line if we found something
1339 // reasonable and not equal to what we showed in the "scanning from here"
1341 if (Best
&& Best
!= StringRef::npos
&& BestQuality
< 50) {
1342 SMRange MatchRange
=
1343 ProcessMatchResult(FileCheckDiag::MatchFuzzy
, SM
, getLoc(),
1344 getCheckTy(), Buffer
, Best
, 0, Diags
);
1345 SM
.PrintMessage(MatchRange
.Start
, SourceMgr::DK_Note
,
1346 "possible intended match here");
1348 // FIXME: If we wanted to be really friendly we would show why the match
1349 // failed, as it can be hard to spot simple one character differences.
1354 FileCheckPatternContext::getPatternVarValue(StringRef VarName
) {
1355 auto VarIter
= GlobalVariableTable
.find(VarName
);
1356 if (VarIter
== GlobalVariableTable
.end())
1357 return make_error
<UndefVarError
>(VarName
);
1359 return VarIter
->second
;
1362 template <class... Types
>
1363 NumericVariable
*FileCheckPatternContext::makeNumericVariable(Types
... args
) {
1364 NumericVariables
.push_back(std::make_unique
<NumericVariable
>(args
...));
1365 return NumericVariables
.back().get();
1369 FileCheckPatternContext::makeStringSubstitution(StringRef VarName
,
1371 Substitutions
.push_back(
1372 std::make_unique
<StringSubstitution
>(this, VarName
, InsertIdx
));
1373 return Substitutions
.back().get();
1376 Substitution
*FileCheckPatternContext::makeNumericSubstitution(
1377 StringRef ExpressionStr
, std::unique_ptr
<Expression
> Expression
,
1379 Substitutions
.push_back(std::make_unique
<NumericSubstitution
>(
1380 this, ExpressionStr
, std::move(Expression
), InsertIdx
));
1381 return Substitutions
.back().get();
1384 size_t Pattern::FindRegexVarEnd(StringRef Str
, SourceMgr
&SM
) {
1385 // Offset keeps track of the current offset within the input Str
1387 // [...] Nesting depth
1388 size_t BracketDepth
= 0;
1390 while (!Str
.empty()) {
1391 if (Str
.startswith("]]") && BracketDepth
== 0)
1393 if (Str
[0] == '\\') {
1394 // Backslash escapes the next char within regexes, so skip them both.
1395 Str
= Str
.substr(2);
1405 if (BracketDepth
== 0) {
1406 SM
.PrintMessage(SMLoc::getFromPointer(Str
.data()),
1407 SourceMgr::DK_Error
,
1408 "missing closing \"]\" for regex variable");
1414 Str
= Str
.substr(1);
1419 return StringRef::npos
;
1422 StringRef
FileCheck::CanonicalizeFile(MemoryBuffer
&MB
,
1423 SmallVectorImpl
<char> &OutputBuffer
) {
1424 OutputBuffer
.reserve(MB
.getBufferSize());
1426 for (const char *Ptr
= MB
.getBufferStart(), *End
= MB
.getBufferEnd();
1427 Ptr
!= End
; ++Ptr
) {
1428 // Eliminate trailing dosish \r.
1429 if (Ptr
<= End
- 2 && Ptr
[0] == '\r' && Ptr
[1] == '\n') {
1433 // If current char is not a horizontal whitespace or if horizontal
1434 // whitespace canonicalization is disabled, dump it to output as is.
1435 if (Req
.NoCanonicalizeWhiteSpace
|| (*Ptr
!= ' ' && *Ptr
!= '\t')) {
1436 OutputBuffer
.push_back(*Ptr
);
1440 // Otherwise, add one space and advance over neighboring space.
1441 OutputBuffer
.push_back(' ');
1442 while (Ptr
+ 1 != End
&& (Ptr
[1] == ' ' || Ptr
[1] == '\t'))
1446 // Add a null byte and then return all but that byte.
1447 OutputBuffer
.push_back('\0');
1448 return StringRef(OutputBuffer
.data(), OutputBuffer
.size() - 1);
1451 FileCheckDiag::FileCheckDiag(const SourceMgr
&SM
,
1452 const Check::FileCheckType
&CheckTy
,
1453 SMLoc CheckLoc
, MatchType MatchTy
,
1454 SMRange InputRange
, StringRef Note
)
1455 : CheckTy(CheckTy
), CheckLoc(CheckLoc
), MatchTy(MatchTy
), Note(Note
) {
1456 auto Start
= SM
.getLineAndColumn(InputRange
.Start
);
1457 auto End
= SM
.getLineAndColumn(InputRange
.End
);
1458 InputStartLine
= Start
.first
;
1459 InputStartCol
= Start
.second
;
1460 InputEndLine
= End
.first
;
1461 InputEndCol
= End
.second
;
1464 static bool IsPartOfWord(char c
) {
1465 return (isAlnum(c
) || c
== '-' || c
== '_');
1468 Check::FileCheckType
&Check::FileCheckType::setCount(int C
) {
1469 assert(Count
> 0 && "zero and negative counts are not supported");
1470 assert((C
== 1 || Kind
== CheckPlain
) &&
1471 "count supported only for plain CHECK directives");
1476 std::string
Check::FileCheckType::getModifiersDescription() const {
1477 if (Modifiers
.none())
1480 raw_string_ostream
OS(Ret
);
1482 if (isLiteralMatch())
1488 std::string
Check::FileCheckType::getDescription(StringRef Prefix
) const {
1489 // Append directive modifiers.
1490 auto WithModifiers
= [this, Prefix
](StringRef Str
) -> std::string
{
1491 return (Prefix
+ Str
+ getModifiersDescription()).str();
1495 case Check::CheckNone
:
1497 case Check::CheckMisspelled
:
1498 return "misspelled";
1499 case Check::CheckPlain
:
1501 return WithModifiers("-COUNT");
1502 return WithModifiers("");
1503 case Check::CheckNext
:
1504 return WithModifiers("-NEXT");
1505 case Check::CheckSame
:
1506 return WithModifiers("-SAME");
1507 case Check::CheckNot
:
1508 return WithModifiers("-NOT");
1509 case Check::CheckDAG
:
1510 return WithModifiers("-DAG");
1511 case Check::CheckLabel
:
1512 return WithModifiers("-LABEL");
1513 case Check::CheckEmpty
:
1514 return WithModifiers("-EMPTY");
1515 case Check::CheckComment
:
1516 return std::string(Prefix
);
1517 case Check::CheckEOF
:
1518 return "implicit EOF";
1519 case Check::CheckBadNot
:
1521 case Check::CheckBadCount
:
1524 llvm_unreachable("unknown FileCheckType");
1527 static std::pair
<Check::FileCheckType
, StringRef
>
1528 FindCheckType(const FileCheckRequest
&Req
, StringRef Buffer
, StringRef Prefix
,
1530 if (Buffer
.size() <= Prefix
.size())
1531 return {Check::CheckNone
, StringRef()};
1533 StringRef Rest
= Buffer
.drop_front(Prefix
.size());
1534 // Check for comment.
1535 if (llvm::is_contained(Req
.CommentPrefixes
, Prefix
)) {
1536 if (Rest
.consume_front(":"))
1537 return {Check::CheckComment
, Rest
};
1538 // Ignore a comment prefix if it has a suffix like "-NOT".
1539 return {Check::CheckNone
, StringRef()};
1542 auto ConsumeModifiers
= [&](Check::FileCheckType Ret
)
1543 -> std::pair
<Check::FileCheckType
, StringRef
> {
1544 if (Rest
.consume_front(":"))
1546 if (!Rest
.consume_front("{"))
1547 return {Check::CheckNone
, StringRef()};
1549 // Parse the modifiers, speparated by commas.
1551 // Allow whitespace in modifiers list.
1552 Rest
= Rest
.ltrim();
1553 if (Rest
.consume_front("LITERAL"))
1554 Ret
.setLiteralMatch();
1556 return {Check::CheckNone
, Rest
};
1557 // Allow whitespace in modifiers list.
1558 Rest
= Rest
.ltrim();
1559 } while (Rest
.consume_front(","));
1560 if (!Rest
.consume_front("}:"))
1561 return {Check::CheckNone
, Rest
};
1565 // Verify that the prefix is followed by directive modifiers or a colon.
1566 if (Rest
.consume_front(":"))
1567 return {Check::CheckPlain
, Rest
};
1568 if (Rest
.front() == '{')
1569 return ConsumeModifiers(Check::CheckPlain
);
1571 if (Rest
.consume_front("_"))
1573 else if (!Rest
.consume_front("-"))
1574 return {Check::CheckNone
, StringRef()};
1576 if (Rest
.consume_front("COUNT-")) {
1578 if (Rest
.consumeInteger(10, Count
))
1579 // Error happened in parsing integer.
1580 return {Check::CheckBadCount
, Rest
};
1581 if (Count
<= 0 || Count
> INT32_MAX
)
1582 return {Check::CheckBadCount
, Rest
};
1583 if (Rest
.front() != ':' && Rest
.front() != '{')
1584 return {Check::CheckBadCount
, Rest
};
1585 return ConsumeModifiers(
1586 Check::FileCheckType(Check::CheckPlain
).setCount(Count
));
1589 // You can't combine -NOT with another suffix.
1590 if (Rest
.startswith("DAG-NOT:") || Rest
.startswith("NOT-DAG:") ||
1591 Rest
.startswith("NEXT-NOT:") || Rest
.startswith("NOT-NEXT:") ||
1592 Rest
.startswith("SAME-NOT:") || Rest
.startswith("NOT-SAME:") ||
1593 Rest
.startswith("EMPTY-NOT:") || Rest
.startswith("NOT-EMPTY:"))
1594 return {Check::CheckBadNot
, Rest
};
1596 if (Rest
.consume_front("NEXT"))
1597 return ConsumeModifiers(Check::CheckNext
);
1599 if (Rest
.consume_front("SAME"))
1600 return ConsumeModifiers(Check::CheckSame
);
1602 if (Rest
.consume_front("NOT"))
1603 return ConsumeModifiers(Check::CheckNot
);
1605 if (Rest
.consume_front("DAG"))
1606 return ConsumeModifiers(Check::CheckDAG
);
1608 if (Rest
.consume_front("LABEL"))
1609 return ConsumeModifiers(Check::CheckLabel
);
1611 if (Rest
.consume_front("EMPTY"))
1612 return ConsumeModifiers(Check::CheckEmpty
);
1614 return {Check::CheckNone
, Rest
};
1617 static std::pair
<Check::FileCheckType
, StringRef
>
1618 FindCheckType(const FileCheckRequest
&Req
, StringRef Buffer
, StringRef Prefix
) {
1619 bool Misspelled
= false;
1620 auto Res
= FindCheckType(Req
, Buffer
, Prefix
, Misspelled
);
1621 if (Res
.first
!= Check::CheckNone
&& Misspelled
)
1622 return {Check::CheckMisspelled
, Res
.second
};
1626 // From the given position, find the next character after the word.
1627 static size_t SkipWord(StringRef Str
, size_t Loc
) {
1628 while (Loc
< Str
.size() && IsPartOfWord(Str
[Loc
]))
1633 /// Searches the buffer for the first prefix in the prefix regular expression.
1635 /// This searches the buffer using the provided regular expression, however it
1636 /// enforces constraints beyond that:
1637 /// 1) The found prefix must not be a suffix of something that looks like
1639 /// 2) The found prefix must be followed by a valid check type suffix using \c
1640 /// FindCheckType above.
1642 /// \returns a pair of StringRefs into the Buffer, which combines:
1643 /// - the first match of the regular expression to satisfy these two is
1645 /// otherwise an empty StringRef is returned to indicate failure.
1646 /// - buffer rewound to the location right after parsed suffix, for parsing
1647 /// to continue from
1649 /// If this routine returns a valid prefix, it will also shrink \p Buffer to
1650 /// start at the beginning of the returned prefix, increment \p LineNumber for
1651 /// each new line consumed from \p Buffer, and set \p CheckTy to the type of
1652 /// check found by examining the suffix.
1654 /// If no valid prefix is found, the state of Buffer, LineNumber, and CheckTy
1656 static std::pair
<StringRef
, StringRef
>
1657 FindFirstMatchingPrefix(const FileCheckRequest
&Req
, Regex
&PrefixRE
,
1658 StringRef
&Buffer
, unsigned &LineNumber
,
1659 Check::FileCheckType
&CheckTy
) {
1660 SmallVector
<StringRef
, 2> Matches
;
1662 while (!Buffer
.empty()) {
1663 // Find the first (longest) match using the RE.
1664 if (!PrefixRE
.match(Buffer
, &Matches
))
1665 // No match at all, bail.
1666 return {StringRef(), StringRef()};
1668 StringRef Prefix
= Matches
[0];
1671 assert(Prefix
.data() >= Buffer
.data() &&
1672 Prefix
.data() < Buffer
.data() + Buffer
.size() &&
1673 "Prefix doesn't start inside of buffer!");
1674 size_t Loc
= Prefix
.data() - Buffer
.data();
1675 StringRef Skipped
= Buffer
.substr(0, Loc
);
1676 Buffer
= Buffer
.drop_front(Loc
);
1677 LineNumber
+= Skipped
.count('\n');
1679 // Check that the matched prefix isn't a suffix of some other check-like
1681 // FIXME: This is a very ad-hoc check. it would be better handled in some
1682 // other way. Among other things it seems hard to distinguish between
1683 // intentional and unintentional uses of this feature.
1684 if (Skipped
.empty() || !IsPartOfWord(Skipped
.back())) {
1685 // Now extract the type.
1686 StringRef AfterSuffix
;
1687 std::tie(CheckTy
, AfterSuffix
) = FindCheckType(Req
, Buffer
, Prefix
);
1689 // If we've found a valid check type for this prefix, we're done.
1690 if (CheckTy
!= Check::CheckNone
)
1691 return {Prefix
, AfterSuffix
};
1694 // If we didn't successfully find a prefix, we need to skip this invalid
1695 // prefix and continue scanning. We directly skip the prefix that was
1696 // matched and any additional parts of that check-like word.
1697 Buffer
= Buffer
.drop_front(SkipWord(Buffer
, Prefix
.size()));
1700 // We ran out of buffer while skipping partial matches so give up.
1701 return {StringRef(), StringRef()};
1704 void FileCheckPatternContext::createLineVariable() {
1705 assert(!LineVariable
&& "@LINE pseudo numeric variable already created");
1706 StringRef LineName
= "@LINE";
1707 LineVariable
= makeNumericVariable(
1708 LineName
, ExpressionFormat(ExpressionFormat::Kind::Unsigned
));
1709 GlobalNumericVariableTable
[LineName
] = LineVariable
;
1712 FileCheck::FileCheck(FileCheckRequest Req
)
1713 : Req(Req
), PatternContext(std::make_unique
<FileCheckPatternContext
>()),
1714 CheckStrings(std::make_unique
<std::vector
<FileCheckString
>>()) {}
1716 FileCheck::~FileCheck() = default;
1718 bool FileCheck::readCheckFile(
1719 SourceMgr
&SM
, StringRef Buffer
, Regex
&PrefixRE
,
1720 std::pair
<unsigned, unsigned> *ImpPatBufferIDRange
) {
1721 if (ImpPatBufferIDRange
)
1722 ImpPatBufferIDRange
->first
= ImpPatBufferIDRange
->second
= 0;
1725 PatternContext
->defineCmdlineVariables(Req
.GlobalDefines
, SM
);
1727 logAllUnhandledErrors(std::move(DefineError
), errs());
1731 PatternContext
->createLineVariable();
1733 std::vector
<Pattern
> ImplicitNegativeChecks
;
1734 for (StringRef PatternString
: Req
.ImplicitCheckNot
) {
1735 // Create a buffer with fake command line content in order to display the
1736 // command line option responsible for the specific implicit CHECK-NOT.
1737 std::string Prefix
= "-implicit-check-not='";
1738 std::string Suffix
= "'";
1739 std::unique_ptr
<MemoryBuffer
> CmdLine
= MemoryBuffer::getMemBufferCopy(
1740 (Prefix
+ PatternString
+ Suffix
).str(), "command line");
1742 StringRef PatternInBuffer
=
1743 CmdLine
->getBuffer().substr(Prefix
.size(), PatternString
.size());
1744 unsigned BufferID
= SM
.AddNewSourceBuffer(std::move(CmdLine
), SMLoc());
1745 if (ImpPatBufferIDRange
) {
1746 if (ImpPatBufferIDRange
->first
== ImpPatBufferIDRange
->second
) {
1747 ImpPatBufferIDRange
->first
= BufferID
;
1748 ImpPatBufferIDRange
->second
= BufferID
+ 1;
1750 assert(BufferID
== ImpPatBufferIDRange
->second
&&
1751 "expected consecutive source buffer IDs");
1752 ++ImpPatBufferIDRange
->second
;
1756 ImplicitNegativeChecks
.push_back(
1757 Pattern(Check::CheckNot
, PatternContext
.get()));
1758 ImplicitNegativeChecks
.back().parsePattern(PatternInBuffer
,
1759 "IMPLICIT-CHECK", SM
, Req
);
1762 std::vector
<Pattern
> DagNotMatches
= ImplicitNegativeChecks
;
1764 // LineNumber keeps track of the line on which CheckPrefix instances are
1766 unsigned LineNumber
= 1;
1768 std::set
<StringRef
> PrefixesNotFound(Req
.CheckPrefixes
.begin(),
1769 Req
.CheckPrefixes
.end());
1770 const size_t DistinctPrefixes
= PrefixesNotFound
.size();
1772 Check::FileCheckType CheckTy
;
1774 // See if a prefix occurs in the memory buffer.
1775 StringRef UsedPrefix
;
1776 StringRef AfterSuffix
;
1777 std::tie(UsedPrefix
, AfterSuffix
) =
1778 FindFirstMatchingPrefix(Req
, PrefixRE
, Buffer
, LineNumber
, CheckTy
);
1779 if (UsedPrefix
.empty())
1781 if (CheckTy
!= Check::CheckComment
)
1782 PrefixesNotFound
.erase(UsedPrefix
);
1784 assert(UsedPrefix
.data() == Buffer
.data() &&
1785 "Failed to move Buffer's start forward, or pointed prefix outside "
1787 assert(AfterSuffix
.data() >= Buffer
.data() &&
1788 AfterSuffix
.data() < Buffer
.data() + Buffer
.size() &&
1789 "Parsing after suffix doesn't start inside of buffer!");
1791 // Location to use for error messages.
1792 const char *UsedPrefixStart
= UsedPrefix
.data();
1794 // Skip the buffer to the end of parsed suffix (or just prefix, if no good
1795 // suffix was processed).
1796 Buffer
= AfterSuffix
.empty() ? Buffer
.drop_front(UsedPrefix
.size())
1799 // Complain about misspelled directives.
1800 if (CheckTy
== Check::CheckMisspelled
) {
1801 StringRef
UsedDirective(UsedPrefix
.data(),
1802 AfterSuffix
.data() - UsedPrefix
.data());
1803 SM
.PrintMessage(SMLoc::getFromPointer(UsedDirective
.data()),
1804 SourceMgr::DK_Error
,
1805 "misspelled directive '" + UsedDirective
+ "'");
1809 // Complain about useful-looking but unsupported suffixes.
1810 if (CheckTy
== Check::CheckBadNot
) {
1811 SM
.PrintMessage(SMLoc::getFromPointer(Buffer
.data()), SourceMgr::DK_Error
,
1812 "unsupported -NOT combo on prefix '" + UsedPrefix
+ "'");
1816 // Complain about invalid count specification.
1817 if (CheckTy
== Check::CheckBadCount
) {
1818 SM
.PrintMessage(SMLoc::getFromPointer(Buffer
.data()), SourceMgr::DK_Error
,
1819 "invalid count in -COUNT specification on prefix '" +
1824 // Okay, we found the prefix, yay. Remember the rest of the line, but ignore
1825 // leading whitespace.
1826 if (!(Req
.NoCanonicalizeWhiteSpace
&& Req
.MatchFullLines
))
1827 Buffer
= Buffer
.substr(Buffer
.find_first_not_of(" \t"));
1829 // Scan ahead to the end of line.
1830 size_t EOL
= Buffer
.find_first_of("\n\r");
1832 // Remember the location of the start of the pattern, for diagnostics.
1833 SMLoc PatternLoc
= SMLoc::getFromPointer(Buffer
.data());
1835 // Extract the pattern from the buffer.
1836 StringRef PatternBuffer
= Buffer
.substr(0, EOL
);
1837 Buffer
= Buffer
.substr(EOL
);
1839 // If this is a comment, we're done.
1840 if (CheckTy
== Check::CheckComment
)
1843 // Parse the pattern.
1844 Pattern
P(CheckTy
, PatternContext
.get(), LineNumber
);
1845 if (P
.parsePattern(PatternBuffer
, UsedPrefix
, SM
, Req
))
1848 // Verify that CHECK-LABEL lines do not define or use variables
1849 if ((CheckTy
== Check::CheckLabel
) && P
.hasVariable()) {
1851 SMLoc::getFromPointer(UsedPrefixStart
), SourceMgr::DK_Error
,
1852 "found '" + UsedPrefix
+ "-LABEL:'"
1853 " with variable definition or use");
1857 // Verify that CHECK-NEXT/SAME/EMPTY lines have at least one CHECK line before them.
1858 if ((CheckTy
== Check::CheckNext
|| CheckTy
== Check::CheckSame
||
1859 CheckTy
== Check::CheckEmpty
) &&
1860 CheckStrings
->empty()) {
1861 StringRef Type
= CheckTy
== Check::CheckNext
1863 : CheckTy
== Check::CheckEmpty
? "EMPTY" : "SAME";
1864 SM
.PrintMessage(SMLoc::getFromPointer(UsedPrefixStart
),
1865 SourceMgr::DK_Error
,
1866 "found '" + UsedPrefix
+ "-" + Type
+
1867 "' without previous '" + UsedPrefix
+ ": line");
1871 // Handle CHECK-DAG/-NOT.
1872 if (CheckTy
== Check::CheckDAG
|| CheckTy
== Check::CheckNot
) {
1873 DagNotMatches
.push_back(P
);
1877 // Okay, add the string we captured to the output vector and move on.
1878 CheckStrings
->emplace_back(P
, UsedPrefix
, PatternLoc
);
1879 std::swap(DagNotMatches
, CheckStrings
->back().DagNotStrings
);
1880 DagNotMatches
= ImplicitNegativeChecks
;
1883 // When there are no used prefixes we report an error except in the case that
1884 // no prefix is specified explicitly but -implicit-check-not is specified.
1885 const bool NoPrefixesFound
= PrefixesNotFound
.size() == DistinctPrefixes
;
1886 const bool SomePrefixesUnexpectedlyNotUsed
=
1887 !Req
.AllowUnusedPrefixes
&& !PrefixesNotFound
.empty();
1888 if ((NoPrefixesFound
|| SomePrefixesUnexpectedlyNotUsed
) &&
1889 (ImplicitNegativeChecks
.empty() || !Req
.IsDefaultCheckPrefix
)) {
1890 errs() << "error: no check strings found with prefix"
1891 << (PrefixesNotFound
.size() > 1 ? "es " : " ");
1893 for (StringRef MissingPrefix
: PrefixesNotFound
) {
1896 errs() << "\'" << MissingPrefix
<< ":'";
1903 // Add an EOF pattern for any trailing --implicit-check-not/CHECK-DAG/-NOTs,
1904 // and use the first prefix as a filler for the error message.
1905 if (!DagNotMatches
.empty()) {
1906 CheckStrings
->emplace_back(
1907 Pattern(Check::CheckEOF
, PatternContext
.get(), LineNumber
+ 1),
1908 *Req
.CheckPrefixes
.begin(), SMLoc::getFromPointer(Buffer
.data()));
1909 std::swap(DagNotMatches
, CheckStrings
->back().DagNotStrings
);
1915 /// Returns either (1) \c ErrorSuccess if there was no error or (2)
1916 /// \c ErrorReported if an error was reported, such as an unexpected match.
1917 static Error
printMatch(bool ExpectedMatch
, const SourceMgr
&SM
,
1918 StringRef Prefix
, SMLoc Loc
, const Pattern
&Pat
,
1919 int MatchedCount
, StringRef Buffer
,
1920 Pattern::MatchResult MatchResult
,
1921 const FileCheckRequest
&Req
,
1922 std::vector
<FileCheckDiag
> *Diags
) {
1923 // Suppress some verbosity if there's no error.
1924 bool HasError
= !ExpectedMatch
|| MatchResult
.TheError
;
1925 bool PrintDiag
= true;
1928 return ErrorReported::reportedOrSuccess(HasError
);
1929 if (!Req
.VerboseVerbose
&& Pat
.getCheckTy() == Check::CheckEOF
)
1930 return ErrorReported::reportedOrSuccess(HasError
);
1931 // Due to their verbosity, we don't print verbose diagnostics here if we're
1932 // gathering them for Diags to be rendered elsewhere, but we always print
1933 // other diagnostics.
1937 // Add "found" diagnostic, substitutions, and variable definitions to Diags.
1938 FileCheckDiag::MatchType MatchTy
= ExpectedMatch
1939 ? FileCheckDiag::MatchFoundAndExpected
1940 : FileCheckDiag::MatchFoundButExcluded
;
1941 SMRange MatchRange
= ProcessMatchResult(MatchTy
, SM
, Loc
, Pat
.getCheckTy(),
1942 Buffer
, MatchResult
.TheMatch
->Pos
,
1943 MatchResult
.TheMatch
->Len
, Diags
);
1945 Pat
.printSubstitutions(SM
, Buffer
, MatchRange
, MatchTy
, Diags
);
1946 Pat
.printVariableDefs(SM
, MatchTy
, Diags
);
1949 assert(!HasError
&& "expected to report more diagnostics for error");
1950 return ErrorReported::reportedOrSuccess(HasError
);
1954 std::string Message
= formatv("{0}: {1} string found in input",
1955 Pat
.getCheckTy().getDescription(Prefix
),
1956 (ExpectedMatch
? "expected" : "excluded"))
1958 if (Pat
.getCount() > 1)
1959 Message
+= formatv(" ({0} out of {1})", MatchedCount
, Pat
.getCount()).str();
1961 Loc
, ExpectedMatch
? SourceMgr::DK_Remark
: SourceMgr::DK_Error
, Message
);
1962 SM
.PrintMessage(MatchRange
.Start
, SourceMgr::DK_Note
, "found here",
1965 // Print additional information, which can be useful even if there are errors.
1966 Pat
.printSubstitutions(SM
, Buffer
, MatchRange
, MatchTy
, nullptr);
1967 Pat
.printVariableDefs(SM
, MatchTy
, nullptr);
1969 // Print errors and add them to Diags. We report these errors after the match
1970 // itself because we found them after the match. If we had found them before
1971 // the match, we'd be in printNoMatch.
1972 handleAllErrors(std::move(MatchResult
.TheError
),
1973 [&](const ErrorDiagnostic
&E
) {
1976 Diags
->emplace_back(SM
, Pat
.getCheckTy(), Loc
,
1977 FileCheckDiag::MatchFoundErrorNote
,
1978 E
.getRange(), E
.getMessage().str());
1981 return ErrorReported::reportedOrSuccess(HasError
);
1984 /// Returns either (1) \c ErrorSuccess if there was no error, or (2)
1985 /// \c ErrorReported if an error was reported, such as an expected match not
1987 static Error
printNoMatch(bool ExpectedMatch
, const SourceMgr
&SM
,
1988 StringRef Prefix
, SMLoc Loc
, const Pattern
&Pat
,
1989 int MatchedCount
, StringRef Buffer
, Error MatchError
,
1990 bool VerboseVerbose
,
1991 std::vector
<FileCheckDiag
> *Diags
) {
1992 // Print any pattern errors, and record them to be added to Diags later.
1993 bool HasError
= ExpectedMatch
;
1994 bool HasPatternError
= false;
1995 FileCheckDiag::MatchType MatchTy
= ExpectedMatch
1996 ? FileCheckDiag::MatchNoneButExpected
1997 : FileCheckDiag::MatchNoneAndExcluded
;
1998 SmallVector
<std::string
, 4> ErrorMsgs
;
2000 std::move(MatchError
),
2001 [&](const ErrorDiagnostic
&E
) {
2002 HasError
= HasPatternError
= true;
2003 MatchTy
= FileCheckDiag::MatchNoneForInvalidPattern
;
2006 ErrorMsgs
.push_back(E
.getMessage().str());
2008 // NotFoundError is why printNoMatch was invoked.
2009 [](const NotFoundError
&E
) {});
2011 // Suppress some verbosity if there's no error.
2012 bool PrintDiag
= true;
2014 if (!VerboseVerbose
)
2015 return ErrorReported::reportedOrSuccess(HasError
);
2016 // Due to their verbosity, we don't print verbose diagnostics here if we're
2017 // gathering them for Diags to be rendered elsewhere, but we always print
2018 // other diagnostics.
2022 // Add "not found" diagnostic, substitutions, and pattern errors to Diags.
2024 // We handle Diags a little differently than the errors we print directly:
2025 // we add the "not found" diagnostic to Diags even if there are pattern
2026 // errors. The reason is that we need to attach pattern errors as notes
2027 // somewhere in the input, and the input search range from the "not found"
2028 // diagnostic is all we have to anchor them.
2029 SMRange SearchRange
= ProcessMatchResult(MatchTy
, SM
, Loc
, Pat
.getCheckTy(),
2030 Buffer
, 0, Buffer
.size(), Diags
);
2032 SMRange NoteRange
= SMRange(SearchRange
.Start
, SearchRange
.Start
);
2033 for (StringRef ErrorMsg
: ErrorMsgs
)
2034 Diags
->emplace_back(SM
, Pat
.getCheckTy(), Loc
, MatchTy
, NoteRange
,
2036 Pat
.printSubstitutions(SM
, Buffer
, SearchRange
, MatchTy
, Diags
);
2039 assert(!HasError
&& "expected to report more diagnostics for error");
2040 return ErrorReported::reportedOrSuccess(HasError
);
2043 // Print "not found" diagnostic, except that's implied if we already printed a
2045 if (!HasPatternError
) {
2046 std::string Message
= formatv("{0}: {1} string not found in input",
2047 Pat
.getCheckTy().getDescription(Prefix
),
2048 (ExpectedMatch
? "expected" : "excluded"))
2050 if (Pat
.getCount() > 1)
2052 formatv(" ({0} out of {1})", MatchedCount
, Pat
.getCount()).str();
2053 SM
.PrintMessage(Loc
,
2054 ExpectedMatch
? SourceMgr::DK_Error
: SourceMgr::DK_Remark
,
2056 SM
.PrintMessage(SearchRange
.Start
, SourceMgr::DK_Note
,
2057 "scanning from here");
2060 // Print additional information, which can be useful even after a pattern
2062 Pat
.printSubstitutions(SM
, Buffer
, SearchRange
, MatchTy
, nullptr);
2064 Pat
.printFuzzyMatch(SM
, Buffer
, Diags
);
2065 return ErrorReported::reportedOrSuccess(HasError
);
2068 /// Returns either (1) \c ErrorSuccess if there was no error, or (2)
2069 /// \c ErrorReported if an error was reported.
2070 static Error
reportMatchResult(bool ExpectedMatch
, const SourceMgr
&SM
,
2071 StringRef Prefix
, SMLoc Loc
, const Pattern
&Pat
,
2072 int MatchedCount
, StringRef Buffer
,
2073 Pattern::MatchResult MatchResult
,
2074 const FileCheckRequest
&Req
,
2075 std::vector
<FileCheckDiag
> *Diags
) {
2076 if (MatchResult
.TheMatch
)
2077 return printMatch(ExpectedMatch
, SM
, Prefix
, Loc
, Pat
, MatchedCount
, Buffer
,
2078 std::move(MatchResult
), Req
, Diags
);
2079 return printNoMatch(ExpectedMatch
, SM
, Prefix
, Loc
, Pat
, MatchedCount
, Buffer
,
2080 std::move(MatchResult
.TheError
), Req
.VerboseVerbose
,
2084 /// Counts the number of newlines in the specified range.
2085 static unsigned CountNumNewlinesBetween(StringRef Range
,
2086 const char *&FirstNewLine
) {
2087 unsigned NumNewLines
= 0;
2089 // Scan for newline.
2090 Range
= Range
.substr(Range
.find_first_of("\n\r"));
2096 // Handle \n\r and \r\n as a single newline.
2097 if (Range
.size() > 1 && (Range
[1] == '\n' || Range
[1] == '\r') &&
2098 (Range
[0] != Range
[1]))
2099 Range
= Range
.substr(1);
2100 Range
= Range
.substr(1);
2102 if (NumNewLines
== 1)
2103 FirstNewLine
= Range
.begin();
2107 size_t FileCheckString::Check(const SourceMgr
&SM
, StringRef Buffer
,
2108 bool IsLabelScanMode
, size_t &MatchLen
,
2109 FileCheckRequest
&Req
,
2110 std::vector
<FileCheckDiag
> *Diags
) const {
2112 std::vector
<const Pattern
*> NotStrings
;
2114 // IsLabelScanMode is true when we are scanning forward to find CHECK-LABEL
2115 // bounds; we have not processed variable definitions within the bounded block
2116 // yet so cannot handle any final CHECK-DAG yet; this is handled when going
2117 // over the block again (including the last CHECK-LABEL) in normal mode.
2118 if (!IsLabelScanMode
) {
2119 // Match "dag strings" (with mixed "not strings" if any).
2120 LastPos
= CheckDag(SM
, Buffer
, NotStrings
, Req
, Diags
);
2121 if (LastPos
== StringRef::npos
)
2122 return StringRef::npos
;
2125 // Match itself from the last position after matching CHECK-DAG.
2126 size_t LastMatchEnd
= LastPos
;
2127 size_t FirstMatchPos
= 0;
2128 // Go match the pattern Count times. Majority of patterns only match with
2130 assert(Pat
.getCount() != 0 && "pattern count can not be zero");
2131 for (int i
= 1; i
<= Pat
.getCount(); i
++) {
2132 StringRef MatchBuffer
= Buffer
.substr(LastMatchEnd
);
2133 // get a match at current start point
2134 Pattern::MatchResult MatchResult
= Pat
.match(MatchBuffer
, SM
);
2137 if (Error Err
= reportMatchResult(/*ExpectedMatch=*/true, SM
, Prefix
, Loc
,
2138 Pat
, i
, MatchBuffer
,
2139 std::move(MatchResult
), Req
, Diags
)) {
2140 cantFail(handleErrors(std::move(Err
), [&](const ErrorReported
&E
) {}));
2141 return StringRef::npos
;
2144 size_t MatchPos
= MatchResult
.TheMatch
->Pos
;
2146 FirstMatchPos
= LastPos
+ MatchPos
;
2148 // move start point after the match
2149 LastMatchEnd
+= MatchPos
+ MatchResult
.TheMatch
->Len
;
2151 // Full match len counts from first match pos.
2152 MatchLen
= LastMatchEnd
- FirstMatchPos
;
2154 // Similar to the above, in "label-scan mode" we can't yet handle CHECK-NEXT
2156 if (!IsLabelScanMode
) {
2157 size_t MatchPos
= FirstMatchPos
- LastPos
;
2158 StringRef MatchBuffer
= Buffer
.substr(LastPos
);
2159 StringRef SkippedRegion
= Buffer
.substr(LastPos
, MatchPos
);
2161 // If this check is a "CHECK-NEXT", verify that the previous match was on
2162 // the previous line (i.e. that there is one newline between them).
2163 if (CheckNext(SM
, SkippedRegion
)) {
2164 ProcessMatchResult(FileCheckDiag::MatchFoundButWrongLine
, SM
, Loc
,
2165 Pat
.getCheckTy(), MatchBuffer
, MatchPos
, MatchLen
,
2166 Diags
, Req
.Verbose
);
2167 return StringRef::npos
;
2170 // If this check is a "CHECK-SAME", verify that the previous match was on
2171 // the same line (i.e. that there is no newline between them).
2172 if (CheckSame(SM
, SkippedRegion
)) {
2173 ProcessMatchResult(FileCheckDiag::MatchFoundButWrongLine
, SM
, Loc
,
2174 Pat
.getCheckTy(), MatchBuffer
, MatchPos
, MatchLen
,
2175 Diags
, Req
.Verbose
);
2176 return StringRef::npos
;
2179 // If this match had "not strings", verify that they don't exist in the
2181 if (CheckNot(SM
, SkippedRegion
, NotStrings
, Req
, Diags
))
2182 return StringRef::npos
;
2185 return FirstMatchPos
;
2188 bool FileCheckString::CheckNext(const SourceMgr
&SM
, StringRef Buffer
) const {
2189 if (Pat
.getCheckTy() != Check::CheckNext
&&
2190 Pat
.getCheckTy() != Check::CheckEmpty
)
2195 Twine(Pat
.getCheckTy() == Check::CheckEmpty
? "-EMPTY" : "-NEXT");
2197 // Count the number of newlines between the previous match and this one.
2198 const char *FirstNewLine
= nullptr;
2199 unsigned NumNewLines
= CountNumNewlinesBetween(Buffer
, FirstNewLine
);
2201 if (NumNewLines
== 0) {
2202 SM
.PrintMessage(Loc
, SourceMgr::DK_Error
,
2203 CheckName
+ ": is on the same line as previous match");
2204 SM
.PrintMessage(SMLoc::getFromPointer(Buffer
.end()), SourceMgr::DK_Note
,
2205 "'next' match was here");
2206 SM
.PrintMessage(SMLoc::getFromPointer(Buffer
.data()), SourceMgr::DK_Note
,
2207 "previous match ended here");
2211 if (NumNewLines
!= 1) {
2212 SM
.PrintMessage(Loc
, SourceMgr::DK_Error
,
2214 ": is not on the line after the previous match");
2215 SM
.PrintMessage(SMLoc::getFromPointer(Buffer
.end()), SourceMgr::DK_Note
,
2216 "'next' match was here");
2217 SM
.PrintMessage(SMLoc::getFromPointer(Buffer
.data()), SourceMgr::DK_Note
,
2218 "previous match ended here");
2219 SM
.PrintMessage(SMLoc::getFromPointer(FirstNewLine
), SourceMgr::DK_Note
,
2220 "non-matching line after previous match is here");
2227 bool FileCheckString::CheckSame(const SourceMgr
&SM
, StringRef Buffer
) const {
2228 if (Pat
.getCheckTy() != Check::CheckSame
)
2231 // Count the number of newlines between the previous match and this one.
2232 const char *FirstNewLine
= nullptr;
2233 unsigned NumNewLines
= CountNumNewlinesBetween(Buffer
, FirstNewLine
);
2235 if (NumNewLines
!= 0) {
2236 SM
.PrintMessage(Loc
, SourceMgr::DK_Error
,
2238 "-SAME: is not on the same line as the previous match");
2239 SM
.PrintMessage(SMLoc::getFromPointer(Buffer
.end()), SourceMgr::DK_Note
,
2240 "'next' match was here");
2241 SM
.PrintMessage(SMLoc::getFromPointer(Buffer
.data()), SourceMgr::DK_Note
,
2242 "previous match ended here");
2249 bool FileCheckString::CheckNot(const SourceMgr
&SM
, StringRef Buffer
,
2250 const std::vector
<const Pattern
*> &NotStrings
,
2251 const FileCheckRequest
&Req
,
2252 std::vector
<FileCheckDiag
> *Diags
) const {
2253 bool DirectiveFail
= false;
2254 for (const Pattern
*Pat
: NotStrings
) {
2255 assert((Pat
->getCheckTy() == Check::CheckNot
) && "Expect CHECK-NOT!");
2256 Pattern::MatchResult MatchResult
= Pat
->match(Buffer
, SM
);
2257 if (Error Err
= reportMatchResult(/*ExpectedMatch=*/false, SM
, Prefix
,
2258 Pat
->getLoc(), *Pat
, 1, Buffer
,
2259 std::move(MatchResult
), Req
, Diags
)) {
2260 cantFail(handleErrors(std::move(Err
), [&](const ErrorReported
&E
) {}));
2261 DirectiveFail
= true;
2265 return DirectiveFail
;
2268 size_t FileCheckString::CheckDag(const SourceMgr
&SM
, StringRef Buffer
,
2269 std::vector
<const Pattern
*> &NotStrings
,
2270 const FileCheckRequest
&Req
,
2271 std::vector
<FileCheckDiag
> *Diags
) const {
2272 if (DagNotStrings
.empty())
2275 // The start of the search range.
2276 size_t StartPos
= 0;
2282 // A sorted list of ranges for non-overlapping CHECK-DAG matches. Match
2283 // ranges are erased from this list once they are no longer in the search
2285 std::list
<MatchRange
> MatchRanges
;
2287 // We need PatItr and PatEnd later for detecting the end of a CHECK-DAG
2288 // group, so we don't use a range-based for loop here.
2289 for (auto PatItr
= DagNotStrings
.begin(), PatEnd
= DagNotStrings
.end();
2290 PatItr
!= PatEnd
; ++PatItr
) {
2291 const Pattern
&Pat
= *PatItr
;
2292 assert((Pat
.getCheckTy() == Check::CheckDAG
||
2293 Pat
.getCheckTy() == Check::CheckNot
) &&
2294 "Invalid CHECK-DAG or CHECK-NOT!");
2296 if (Pat
.getCheckTy() == Check::CheckNot
) {
2297 NotStrings
.push_back(&Pat
);
2301 assert((Pat
.getCheckTy() == Check::CheckDAG
) && "Expect CHECK-DAG!");
2303 // CHECK-DAG always matches from the start.
2304 size_t MatchLen
= 0, MatchPos
= StartPos
;
2306 // Search for a match that doesn't overlap a previous match in this
2308 for (auto MI
= MatchRanges
.begin(), ME
= MatchRanges
.end(); true; ++MI
) {
2309 StringRef MatchBuffer
= Buffer
.substr(MatchPos
);
2310 Pattern::MatchResult MatchResult
= Pat
.match(MatchBuffer
, SM
);
2311 // With a group of CHECK-DAGs, a single mismatching means the match on
2312 // that group of CHECK-DAGs fails immediately.
2313 if (MatchResult
.TheError
|| Req
.VerboseVerbose
) {
2314 if (Error Err
= reportMatchResult(/*ExpectedMatch=*/true, SM
, Prefix
,
2315 Pat
.getLoc(), Pat
, 1, MatchBuffer
,
2316 std::move(MatchResult
), Req
, Diags
)) {
2318 handleErrors(std::move(Err
), [&](const ErrorReported
&E
) {}));
2319 return StringRef::npos
;
2322 MatchLen
= MatchResult
.TheMatch
->Len
;
2323 // Re-calc it as the offset relative to the start of the original
2325 MatchPos
+= MatchResult
.TheMatch
->Pos
;
2326 MatchRange M
{MatchPos
, MatchPos
+ MatchLen
};
2327 if (Req
.AllowDeprecatedDagOverlap
) {
2328 // We don't need to track all matches in this mode, so we just maintain
2329 // one match range that encompasses the current CHECK-DAG group's
2331 if (MatchRanges
.empty())
2332 MatchRanges
.insert(MatchRanges
.end(), M
);
2334 auto Block
= MatchRanges
.begin();
2335 Block
->Pos
= std::min(Block
->Pos
, M
.Pos
);
2336 Block
->End
= std::max(Block
->End
, M
.End
);
2340 // Iterate previous matches until overlapping match or insertion point.
2341 bool Overlap
= false;
2342 for (; MI
!= ME
; ++MI
) {
2343 if (M
.Pos
< MI
->End
) {
2344 // !Overlap => New match has no overlap and is before this old match.
2345 // Overlap => New match overlaps this old match.
2346 Overlap
= MI
->Pos
< M
.End
;
2351 // Insert non-overlapping match into list.
2352 MatchRanges
.insert(MI
, M
);
2355 if (Req
.VerboseVerbose
) {
2356 // Due to their verbosity, we don't print verbose diagnostics here if
2357 // we're gathering them for a different rendering, but we always print
2358 // other diagnostics.
2360 SMLoc OldStart
= SMLoc::getFromPointer(Buffer
.data() + MI
->Pos
);
2361 SMLoc OldEnd
= SMLoc::getFromPointer(Buffer
.data() + MI
->End
);
2362 SMRange
OldRange(OldStart
, OldEnd
);
2363 SM
.PrintMessage(OldStart
, SourceMgr::DK_Note
,
2364 "match discarded, overlaps earlier DAG match here",
2367 SMLoc CheckLoc
= Diags
->rbegin()->CheckLoc
;
2368 for (auto I
= Diags
->rbegin(), E
= Diags
->rend();
2369 I
!= E
&& I
->CheckLoc
== CheckLoc
; ++I
)
2370 I
->MatchTy
= FileCheckDiag::MatchFoundButDiscarded
;
2375 if (!Req
.VerboseVerbose
)
2376 cantFail(printMatch(
2377 /*ExpectedMatch=*/true, SM
, Prefix
, Pat
.getLoc(), Pat
, 1, Buffer
,
2378 Pattern::MatchResult(MatchPos
, MatchLen
, Error::success()), Req
,
2381 // Handle the end of a CHECK-DAG group.
2382 if (std::next(PatItr
) == PatEnd
||
2383 std::next(PatItr
)->getCheckTy() == Check::CheckNot
) {
2384 if (!NotStrings
.empty()) {
2385 // If there are CHECK-NOTs between two CHECK-DAGs or from CHECK to
2386 // CHECK-DAG, verify that there are no 'not' strings occurred in that
2388 StringRef SkippedRegion
=
2389 Buffer
.slice(StartPos
, MatchRanges
.begin()->Pos
);
2390 if (CheckNot(SM
, SkippedRegion
, NotStrings
, Req
, Diags
))
2391 return StringRef::npos
;
2392 // Clear "not strings".
2395 // All subsequent CHECK-DAGs and CHECK-NOTs should be matched from the
2396 // end of this CHECK-DAG group's match range.
2397 StartPos
= MatchRanges
.rbegin()->End
;
2398 // Don't waste time checking for (impossible) overlaps before that.
2399 MatchRanges
.clear();
2406 static bool ValidatePrefixes(StringRef Kind
, StringSet
<> &UniquePrefixes
,
2407 ArrayRef
<StringRef
> SuppliedPrefixes
) {
2408 for (StringRef Prefix
: SuppliedPrefixes
) {
2409 if (Prefix
.empty()) {
2410 errs() << "error: supplied " << Kind
<< " prefix must not be the empty "
2414 static const Regex
Validator("^[a-zA-Z0-9_-]*$");
2415 if (!Validator
.match(Prefix
)) {
2416 errs() << "error: supplied " << Kind
<< " prefix must start with a "
2417 << "letter and contain only alphanumeric characters, hyphens, and "
2418 << "underscores: '" << Prefix
<< "'\n";
2421 if (!UniquePrefixes
.insert(Prefix
).second
) {
2422 errs() << "error: supplied " << Kind
<< " prefix must be unique among "
2423 << "check and comment prefixes: '" << Prefix
<< "'\n";
2430 static const char *DefaultCheckPrefixes
[] = {"CHECK"};
2431 static const char *DefaultCommentPrefixes
[] = {"COM", "RUN"};
2433 bool FileCheck::ValidateCheckPrefixes() {
2434 StringSet
<> UniquePrefixes
;
2435 // Add default prefixes to catch user-supplied duplicates of them below.
2436 if (Req
.CheckPrefixes
.empty()) {
2437 for (const char *Prefix
: DefaultCheckPrefixes
)
2438 UniquePrefixes
.insert(Prefix
);
2440 if (Req
.CommentPrefixes
.empty()) {
2441 for (const char *Prefix
: DefaultCommentPrefixes
)
2442 UniquePrefixes
.insert(Prefix
);
2444 // Do not validate the default prefixes, or diagnostics about duplicates might
2445 // incorrectly indicate that they were supplied by the user.
2446 if (!ValidatePrefixes("check", UniquePrefixes
, Req
.CheckPrefixes
))
2448 if (!ValidatePrefixes("comment", UniquePrefixes
, Req
.CommentPrefixes
))
2453 Regex
FileCheck::buildCheckPrefixRegex() {
2454 if (Req
.CheckPrefixes
.empty()) {
2455 for (const char *Prefix
: DefaultCheckPrefixes
)
2456 Req
.CheckPrefixes
.push_back(Prefix
);
2457 Req
.IsDefaultCheckPrefix
= true;
2459 if (Req
.CommentPrefixes
.empty()) {
2460 for (const char *Prefix
: DefaultCommentPrefixes
)
2461 Req
.CommentPrefixes
.push_back(Prefix
);
2464 // We already validated the contents of CheckPrefixes and CommentPrefixes so
2465 // just concatenate them as alternatives.
2466 SmallString
<32> PrefixRegexStr
;
2467 for (size_t I
= 0, E
= Req
.CheckPrefixes
.size(); I
!= E
; ++I
) {
2469 PrefixRegexStr
.push_back('|');
2470 PrefixRegexStr
.append(Req
.CheckPrefixes
[I
]);
2472 for (StringRef Prefix
: Req
.CommentPrefixes
) {
2473 PrefixRegexStr
.push_back('|');
2474 PrefixRegexStr
.append(Prefix
);
2477 return Regex(PrefixRegexStr
);
2480 Error
FileCheckPatternContext::defineCmdlineVariables(
2481 ArrayRef
<StringRef
> CmdlineDefines
, SourceMgr
&SM
) {
2482 assert(GlobalVariableTable
.empty() && GlobalNumericVariableTable
.empty() &&
2483 "Overriding defined variable with command-line variable definitions");
2485 if (CmdlineDefines
.empty())
2486 return Error::success();
2488 // Create a string representing the vector of command-line definitions. Each
2489 // definition is on its own line and prefixed with a definition number to
2490 // clarify which definition a given diagnostic corresponds to.
2492 Error Errs
= Error::success();
2493 std::string CmdlineDefsDiag
;
2494 SmallVector
<std::pair
<size_t, size_t>, 4> CmdlineDefsIndices
;
2495 for (StringRef CmdlineDef
: CmdlineDefines
) {
2496 std::string DefPrefix
= ("Global define #" + Twine(++I
) + ": ").str();
2497 size_t EqIdx
= CmdlineDef
.find('=');
2498 if (EqIdx
== StringRef::npos
) {
2499 CmdlineDefsIndices
.push_back(std::make_pair(CmdlineDefsDiag
.size(), 0));
2502 // Numeric variable definition.
2503 if (CmdlineDef
[0] == '#') {
2504 // Append a copy of the command-line definition adapted to use the same
2505 // format as in the input file to be able to reuse
2506 // parseNumericSubstitutionBlock.
2507 CmdlineDefsDiag
+= (DefPrefix
+ CmdlineDef
+ " (parsed as: [[").str();
2508 std::string SubstitutionStr
= std::string(CmdlineDef
);
2509 SubstitutionStr
[EqIdx
] = ':';
2510 CmdlineDefsIndices
.push_back(
2511 std::make_pair(CmdlineDefsDiag
.size(), SubstitutionStr
.size()));
2512 CmdlineDefsDiag
+= (SubstitutionStr
+ Twine("]])\n")).str();
2514 CmdlineDefsDiag
+= DefPrefix
;
2515 CmdlineDefsIndices
.push_back(
2516 std::make_pair(CmdlineDefsDiag
.size(), CmdlineDef
.size()));
2517 CmdlineDefsDiag
+= (CmdlineDef
+ "\n").str();
2521 // Create a buffer with fake command line content in order to display
2522 // parsing diagnostic with location information and point to the
2523 // global definition with invalid syntax.
2524 std::unique_ptr
<MemoryBuffer
> CmdLineDefsDiagBuffer
=
2525 MemoryBuffer::getMemBufferCopy(CmdlineDefsDiag
, "Global defines");
2526 StringRef CmdlineDefsDiagRef
= CmdLineDefsDiagBuffer
->getBuffer();
2527 SM
.AddNewSourceBuffer(std::move(CmdLineDefsDiagBuffer
), SMLoc());
2529 for (std::pair
<size_t, size_t> CmdlineDefIndices
: CmdlineDefsIndices
) {
2530 StringRef CmdlineDef
= CmdlineDefsDiagRef
.substr(CmdlineDefIndices
.first
,
2531 CmdlineDefIndices
.second
);
2532 if (CmdlineDef
.empty()) {
2535 ErrorDiagnostic::get(SM
, CmdlineDef
,
2536 "missing equal sign in global definition"));
2540 // Numeric variable definition.
2541 if (CmdlineDef
[0] == '#') {
2542 // Now parse the definition both to check that the syntax is correct and
2543 // to create the necessary class instance.
2544 StringRef CmdlineDefExpr
= CmdlineDef
.substr(1);
2545 std::optional
<NumericVariable
*> DefinedNumericVariable
;
2546 Expected
<std::unique_ptr
<Expression
>> ExpressionResult
=
2547 Pattern::parseNumericSubstitutionBlock(CmdlineDefExpr
,
2548 DefinedNumericVariable
, false,
2549 std::nullopt
, this, SM
);
2550 if (!ExpressionResult
) {
2551 Errs
= joinErrors(std::move(Errs
), ExpressionResult
.takeError());
2554 std::unique_ptr
<Expression
> Expression
= std::move(*ExpressionResult
);
2555 // Now evaluate the expression whose value this variable should be set
2556 // to, since the expression of a command-line variable definition should
2557 // only use variables defined earlier on the command-line. If not, this
2558 // is an error and we report it.
2559 Expected
<APInt
> Value
= Expression
->getAST()->eval();
2561 Errs
= joinErrors(std::move(Errs
), Value
.takeError());
2565 assert(DefinedNumericVariable
&& "No variable defined");
2566 (*DefinedNumericVariable
)->setValue(*Value
);
2568 // Record this variable definition.
2569 GlobalNumericVariableTable
[(*DefinedNumericVariable
)->getName()] =
2570 *DefinedNumericVariable
;
2572 // String variable definition.
2573 std::pair
<StringRef
, StringRef
> CmdlineNameVal
= CmdlineDef
.split('=');
2574 StringRef CmdlineName
= CmdlineNameVal
.first
;
2575 StringRef OrigCmdlineName
= CmdlineName
;
2576 Expected
<Pattern::VariableProperties
> ParseVarResult
=
2577 Pattern::parseVariable(CmdlineName
, SM
);
2578 if (!ParseVarResult
) {
2579 Errs
= joinErrors(std::move(Errs
), ParseVarResult
.takeError());
2582 // Check that CmdlineName does not denote a pseudo variable is only
2583 // composed of the parsed numeric variable. This catches cases like
2584 // "FOO+2" in a "FOO+2=10" definition.
2585 if (ParseVarResult
->IsPseudo
|| !CmdlineName
.empty()) {
2586 Errs
= joinErrors(std::move(Errs
),
2587 ErrorDiagnostic::get(
2588 SM
, OrigCmdlineName
,
2589 "invalid name in string variable definition '" +
2590 OrigCmdlineName
+ "'"));
2593 StringRef Name
= ParseVarResult
->Name
;
2595 // Detect collisions between string and numeric variables when the former
2596 // is created later than the latter.
2597 if (GlobalNumericVariableTable
.contains(Name
)) {
2598 Errs
= joinErrors(std::move(Errs
),
2599 ErrorDiagnostic::get(SM
, Name
,
2600 "numeric variable with name '" +
2601 Name
+ "' already exists"));
2604 GlobalVariableTable
.insert(CmdlineNameVal
);
2605 // Mark the string variable as defined to detect collisions between
2606 // string and numeric variables in defineCmdlineVariables when the latter
2607 // is created later than the former. We cannot reuse GlobalVariableTable
2608 // for this by populating it with an empty string since we would then
2609 // lose the ability to detect the use of an undefined variable in
2611 DefinedVariableTable
[Name
] = true;
2618 void FileCheckPatternContext::clearLocalVars() {
2619 SmallVector
<StringRef
, 16> LocalPatternVars
, LocalNumericVars
;
2620 for (const StringMapEntry
<StringRef
> &Var
: GlobalVariableTable
)
2621 if (Var
.first()[0] != '$')
2622 LocalPatternVars
.push_back(Var
.first());
2624 // Numeric substitution reads the value of a variable directly, not via
2625 // GlobalNumericVariableTable. Therefore, we clear local variables by
2626 // clearing their value which will lead to a numeric substitution failure. We
2627 // also mark the variable for removal from GlobalNumericVariableTable since
2628 // this is what defineCmdlineVariables checks to decide that no global
2629 // variable has been defined.
2630 for (const auto &Var
: GlobalNumericVariableTable
)
2631 if (Var
.first()[0] != '$') {
2632 Var
.getValue()->clearValue();
2633 LocalNumericVars
.push_back(Var
.first());
2636 for (const auto &Var
: LocalPatternVars
)
2637 GlobalVariableTable
.erase(Var
);
2638 for (const auto &Var
: LocalNumericVars
)
2639 GlobalNumericVariableTable
.erase(Var
);
2642 bool FileCheck::checkInput(SourceMgr
&SM
, StringRef Buffer
,
2643 std::vector
<FileCheckDiag
> *Diags
) {
2644 bool ChecksFailed
= false;
2646 unsigned i
= 0, j
= 0, e
= CheckStrings
->size();
2648 StringRef CheckRegion
;
2650 CheckRegion
= Buffer
;
2652 const FileCheckString
&CheckLabelStr
= (*CheckStrings
)[j
];
2653 if (CheckLabelStr
.Pat
.getCheckTy() != Check::CheckLabel
) {
2658 // Scan to next CHECK-LABEL match, ignoring CHECK-NOT and CHECK-DAG
2659 size_t MatchLabelLen
= 0;
2660 size_t MatchLabelPos
=
2661 CheckLabelStr
.Check(SM
, Buffer
, true, MatchLabelLen
, Req
, Diags
);
2662 if (MatchLabelPos
== StringRef::npos
)
2663 // Immediately bail if CHECK-LABEL fails, nothing else we can do.
2666 CheckRegion
= Buffer
.substr(0, MatchLabelPos
+ MatchLabelLen
);
2667 Buffer
= Buffer
.substr(MatchLabelPos
+ MatchLabelLen
);
2671 // Do not clear the first region as it's the one before the first
2672 // CHECK-LABEL and it would clear variables defined on the command-line
2673 // before they get used.
2674 if (i
!= 0 && Req
.EnableVarScope
)
2675 PatternContext
->clearLocalVars();
2677 for (; i
!= j
; ++i
) {
2678 const FileCheckString
&CheckStr
= (*CheckStrings
)[i
];
2680 // Check each string within the scanned region, including a second check
2681 // of any final CHECK-LABEL (to verify CHECK-NOT and CHECK-DAG)
2682 size_t MatchLen
= 0;
2684 CheckStr
.Check(SM
, CheckRegion
, false, MatchLen
, Req
, Diags
);
2686 if (MatchPos
== StringRef::npos
) {
2687 ChecksFailed
= true;
2692 CheckRegion
= CheckRegion
.substr(MatchPos
+ MatchLen
);
2699 // Success if no checks failed.
2700 return !ChecksFailed
;