FileCheck.cpp revision 178504b07b793b3fde46d950b8f10e0794193e02
181cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner//===- FileCheck.cpp - Check that File's Contents match what is expected --===//
281cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner//
381cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner//                     The LLVM Compiler Infrastructure
481cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner//
581cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner// This file is distributed under the University of Illinois Open Source
681cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner// License. See LICENSE.TXT for details.
781cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner//
881cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner//===----------------------------------------------------------------------===//
981cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner//
1081cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner// FileCheck does a line-by line check of a file that validates whether it
1181cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner// contains the expected content.  This is useful for regression tests etc.
1281cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner//
1381cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner// This program exits with an error status of 2 on error, exit status of 0 if
1481cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner// the file matched the expected contents, and exit status of 1 if it did not
1581cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner// contain the expected contents.
1681cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner//
1781cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner//===----------------------------------------------------------------------===//
1881cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner
193ff9563c3e391954b2e224afcf8b2b0fcc3888aaMichael J. Spencer#include "llvm/ADT/OwningPtr.h"
204ffd89fa4d2788611187d1a534d2ed46adf1702cChandler Carruth#include "llvm/ADT/SmallString.h"
214ffd89fa4d2788611187d1a534d2ed46adf1702cChandler Carruth#include "llvm/ADT/StringExtras.h"
224ffd89fa4d2788611187d1a534d2ed46adf1702cChandler Carruth#include "llvm/ADT/StringMap.h"
2381cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner#include "llvm/Support/CommandLine.h"
2481cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner#include "llvm/Support/MemoryBuffer.h"
2581cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner#include "llvm/Support/PrettyStackTrace.h"
26528700863adefca8de461ce28a7d903729fb96b4Chris Lattner#include "llvm/Support/Regex.h"
274ffd89fa4d2788611187d1a534d2ed46adf1702cChandler Carruth#include "llvm/Support/Signals.h"
2881cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner#include "llvm/Support/SourceMgr.h"
2981cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner#include "llvm/Support/raw_ostream.h"
30333fb04506233255f10d8095c9e2de5e5f0fdc6fMichael J. Spencer#include "llvm/Support/system_error.h"
31eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner#include <algorithm>
329756ca7ba0c7f6c3b1e76ee12ca27ddca04be9d7Eli Bendersky#include <map>
339756ca7ba0c7f6c3b1e76ee12ca27ddca04be9d7Eli Bendersky#include <string>
349756ca7ba0c7f6c3b1e76ee12ca27ddca04be9d7Eli Bendersky#include <vector>
3581cb8caa3eb482d45e0fd54f8022384256619178Chris Lattnerusing namespace llvm;
3681cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner
3781cb8caa3eb482d45e0fd54f8022384256619178Chris Lattnerstatic cl::opt<std::string>
3881cb8caa3eb482d45e0fd54f8022384256619178Chris LattnerCheckFilename(cl::Positional, cl::desc("<check-file>"), cl::Required);
3981cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner
4081cb8caa3eb482d45e0fd54f8022384256619178Chris Lattnerstatic cl::opt<std::string>
4181cb8caa3eb482d45e0fd54f8022384256619178Chris LattnerInputFilename("input-file", cl::desc("File to check (defaults to stdin)"),
4281cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner              cl::init("-"), cl::value_desc("filename"));
4381cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner
4481cb8caa3eb482d45e0fd54f8022384256619178Chris Lattnerstatic cl::opt<std::string>
4581cb8caa3eb482d45e0fd54f8022384256619178Chris LattnerCheckPrefix("check-prefix", cl::init("CHECK"),
4681cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner            cl::desc("Prefix to use from check file (defaults to 'CHECK')"));
4781cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner
4888a7e9ee8dd2f1d2f40cdb9c378f050e45161783Chris Lattnerstatic cl::opt<bool>
4988a7e9ee8dd2f1d2f40cdb9c378f050e45161783Chris LattnerNoCanonicalizeWhiteSpace("strict-whitespace",
5088a7e9ee8dd2f1d2f40cdb9c378f050e45161783Chris Lattner              cl::desc("Do not treat all horizontal whitespace as equivalent"));
5188a7e9ee8dd2f1d2f40cdb9c378f050e45161783Chris Lattner
52a29703e8426763fa5232f9a91e6a5fce4d4244d6Chris Lattner//===----------------------------------------------------------------------===//
53a29703e8426763fa5232f9a91e6a5fce4d4244d6Chris Lattner// Pattern Handling Code.
54a29703e8426763fa5232f9a91e6a5fce4d4244d6Chris Lattner//===----------------------------------------------------------------------===//
55a29703e8426763fa5232f9a91e6a5fce4d4244d6Chris Lattner
569fc6678bea11f32acba4e9b6624ae9a0d3a9287bChris Lattnerclass Pattern {
5794638f0081b6ec8c7cc5ad9fec8ddbdd6824d90dChris Lattner  SMLoc PatternLoc;
587112c86fc208145334aaa04812c794ce6feef416Mikhail Glushenkov
59824c10ece26fd031591b1770acc8a6c2575a3ab8Jakob Stoklund Olesen  /// MatchEOF - When set, this pattern only matches the end of file. This is
60824c10ece26fd031591b1770acc8a6c2575a3ab8Jakob Stoklund Olesen  /// used for trailing CHECK-NOTs.
61824c10ece26fd031591b1770acc8a6c2575a3ab8Jakob Stoklund Olesen  bool MatchEOF;
62824c10ece26fd031591b1770acc8a6c2575a3ab8Jakob Stoklund Olesen
6395ab32667456b13ad56634cc7554cde8a50db95aMichael Liao  /// MatchNot
6495ab32667456b13ad56634cc7554cde8a50db95aMichael Liao  bool MatchNot;
6595ab32667456b13ad56634cc7554cde8a50db95aMichael Liao
6695ab32667456b13ad56634cc7554cde8a50db95aMichael Liao  /// MatchDag
6795ab32667456b13ad56634cc7554cde8a50db95aMichael Liao  bool MatchDag;
6895ab32667456b13ad56634cc7554cde8a50db95aMichael Liao
695d6a05f4d4faea0c0c96fbf2bb57655df2839b34Chris Lattner  /// FixedStr - If non-empty, this pattern is a fixed string match with the
705d6a05f4d4faea0c0c96fbf2bb57655df2839b34Chris Lattner  /// specified fixed string.
712702e6aa53f603b20c3e46364bc1756788bd291aChris Lattner  StringRef FixedStr;
727112c86fc208145334aaa04812c794ce6feef416Mikhail Glushenkov
735d6a05f4d4faea0c0c96fbf2bb57655df2839b34Chris Lattner  /// RegEx - If non-empty, this is a regex pattern.
745d6a05f4d4faea0c0c96fbf2bb57655df2839b34Chris Lattner  std::string RegExStr;
757112c86fc208145334aaa04812c794ce6feef416Mikhail Glushenkov
7670a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko  /// \brief Contains the number of line this pattern is in.
7770a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko  unsigned LineNumber;
7870a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko
79eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner  /// VariableUses - Entries in this vector map to uses of a variable in the
80eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner  /// pattern, e.g. "foo[[bar]]baz".  In this case, the RegExStr will contain
81eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner  /// "foobaz" and we'll get an entry in this vector that tells us to insert the
82eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner  /// value of bar at offset 3.
83eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner  std::vector<std::pair<StringRef, unsigned> > VariableUses;
847112c86fc208145334aaa04812c794ce6feef416Mikhail Glushenkov
859756ca7ba0c7f6c3b1e76ee12ca27ddca04be9d7Eli Bendersky  /// VariableDefs - Maps definitions of variables to their parenthesized
869756ca7ba0c7f6c3b1e76ee12ca27ddca04be9d7Eli Bendersky  /// capture numbers.
879756ca7ba0c7f6c3b1e76ee12ca27ddca04be9d7Eli Bendersky  /// E.g. for the pattern "foo[[bar:.*]]baz", VariableDefs will map "bar" to 1.
889756ca7ba0c7f6c3b1e76ee12ca27ddca04be9d7Eli Bendersky  std::map<StringRef, unsigned> VariableDefs;
897112c86fc208145334aaa04812c794ce6feef416Mikhail Glushenkov
909fc6678bea11f32acba4e9b6624ae9a0d3a9287bChris Lattnerpublic:
917112c86fc208145334aaa04812c794ce6feef416Mikhail Glushenkov
9295ab32667456b13ad56634cc7554cde8a50db95aMichael Liao  Pattern(bool matchEOF = false)
9395ab32667456b13ad56634cc7554cde8a50db95aMichael Liao    : MatchEOF(matchEOF), MatchNot(false), MatchDag(false) { }
947112c86fc208145334aaa04812c794ce6feef416Mikhail Glushenkov
950fc7137f2f8a99cb749024c51e3247f4b24e1ee0Michael Liao  /// getLoc - Return the location in source code.
960fc7137f2f8a99cb749024c51e3247f4b24e1ee0Michael Liao  SMLoc getLoc() const { return PatternLoc; }
970fc7137f2f8a99cb749024c51e3247f4b24e1ee0Michael Liao
981e5cbcb10adaca5c80121293b6c414d9285ebceeEli Bendersky  /// ParsePattern - Parse the given string into the Pattern.  SM provides the
991e5cbcb10adaca5c80121293b6c414d9285ebceeEli Bendersky  /// SourceMgr used for error reports, and LineNumber is the line number in
1001e5cbcb10adaca5c80121293b6c414d9285ebceeEli Bendersky  /// the input file from which the pattern string was read.
1011e5cbcb10adaca5c80121293b6c414d9285ebceeEli Bendersky  /// Returns true in case of an error, false otherwise.
10270a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko  bool ParsePattern(StringRef PatternStr, SourceMgr &SM, unsigned LineNumber);
1037112c86fc208145334aaa04812c794ce6feef416Mikhail Glushenkov
1049fc6678bea11f32acba4e9b6624ae9a0d3a9287bChris Lattner  /// Match - Match the pattern string against the input buffer Buffer.  This
1059fc6678bea11f32acba4e9b6624ae9a0d3a9287bChris Lattner  /// returns the position that is matched or npos if there is no match.  If
1069fc6678bea11f32acba4e9b6624ae9a0d3a9287bChris Lattner  /// there is a match, the size of the matched string is returned in MatchLen.
107eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner  ///
108eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner  /// The VariableTable StringMap provides the current values of filecheck
109eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner  /// variables and is updated if this match defines new values.
110eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner  size_t Match(StringRef Buffer, size_t &MatchLen,
111eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner               StringMap<StringRef> &VariableTable) const;
112fafe93c8bcbc538573bc5e890f24f9869a11f846Daniel Dunbar
113fafe93c8bcbc538573bc5e890f24f9869a11f846Daniel Dunbar  /// PrintFailureInfo - Print additional information about a failure to match
114fafe93c8bcbc538573bc5e890f24f9869a11f846Daniel Dunbar  /// involving this pattern.
115fafe93c8bcbc538573bc5e890f24f9869a11f846Daniel Dunbar  void PrintFailureInfo(const SourceMgr &SM, StringRef Buffer,
116fafe93c8bcbc538573bc5e890f24f9869a11f846Daniel Dunbar                        const StringMap<StringRef> &VariableTable) const;
117fafe93c8bcbc538573bc5e890f24f9869a11f846Daniel Dunbar
118178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin  bool hasVariable() const { return !(VariableUses.empty() &&
119178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin                                      VariableDefs.empty()); }
120178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin
12195ab32667456b13ad56634cc7554cde8a50db95aMichael Liao  void setMatchNot(bool Not) { MatchNot = Not; }
12295ab32667456b13ad56634cc7554cde8a50db95aMichael Liao  bool getMatchNot() const { return MatchNot; }
12395ab32667456b13ad56634cc7554cde8a50db95aMichael Liao
12495ab32667456b13ad56634cc7554cde8a50db95aMichael Liao  void setMatchDag(bool Dag) { MatchDag = Dag; }
12595ab32667456b13ad56634cc7554cde8a50db95aMichael Liao  bool getMatchDag() const { return MatchDag; }
12695ab32667456b13ad56634cc7554cde8a50db95aMichael Liao
1275d6a05f4d4faea0c0c96fbf2bb57655df2839b34Chris Lattnerprivate:
128eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner  static void AddFixedStringToRegEx(StringRef FixedStr, std::string &TheStr);
1299756ca7ba0c7f6c3b1e76ee12ca27ddca04be9d7Eli Bendersky  bool AddRegExToRegEx(StringRef RS, unsigned &CurParen, SourceMgr &SM);
1309756ca7ba0c7f6c3b1e76ee12ca27ddca04be9d7Eli Bendersky  void AddBackrefToRegEx(unsigned BackrefNum);
131ead2dacc9ee028906cb104c8c3d66ccbbebe6b10Daniel Dunbar
132ead2dacc9ee028906cb104c8c3d66ccbbebe6b10Daniel Dunbar  /// ComputeMatchDistance - Compute an arbitrary estimate for the quality of
133ead2dacc9ee028906cb104c8c3d66ccbbebe6b10Daniel Dunbar  /// matching this pattern at the start of \arg Buffer; a distance of zero
134ead2dacc9ee028906cb104c8c3d66ccbbebe6b10Daniel Dunbar  /// should correspond to a perfect match.
135ead2dacc9ee028906cb104c8c3d66ccbbebe6b10Daniel Dunbar  unsigned ComputeMatchDistance(StringRef Buffer,
136ead2dacc9ee028906cb104c8c3d66ccbbebe6b10Daniel Dunbar                               const StringMap<StringRef> &VariableTable) const;
13770a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko
13870a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko  /// \brief Evaluates expression and stores the result to \p Value.
13970a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko  /// \return true on success. false when the expression has invalid syntax.
14070a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko  bool EvaluateExpression(StringRef Expr, std::string &Value) const;
1414db6511779e70780f7b36bb7ef54276752f5f640Eli Bendersky
1424db6511779e70780f7b36bb7ef54276752f5f640Eli Bendersky  /// \brief Finds the closing sequence of a regex variable usage or
1434db6511779e70780f7b36bb7ef54276752f5f640Eli Bendersky  /// definition. Str has to point in the beginning of the definition
1444db6511779e70780f7b36bb7ef54276752f5f640Eli Bendersky  /// (right after the opening sequence).
1454db6511779e70780f7b36bb7ef54276752f5f640Eli Bendersky  /// \return offset of the closing sequence within Str, or npos if it was not
1464db6511779e70780f7b36bb7ef54276752f5f640Eli Bendersky  /// found.
1474db6511779e70780f7b36bb7ef54276752f5f640Eli Bendersky  size_t FindRegexVarEnd(StringRef Str);
1489fc6678bea11f32acba4e9b6624ae9a0d3a9287bChris Lattner};
1499fc6678bea11f32acba4e9b6624ae9a0d3a9287bChris Lattner
150eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner
15170a870add82dab944b98ee1840fafff33795fc95Alexander Kornienkobool Pattern::ParsePattern(StringRef PatternStr, SourceMgr &SM,
15270a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko                           unsigned LineNumber) {
15370a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko  this->LineNumber = LineNumber;
15494638f0081b6ec8c7cc5ad9fec8ddbdd6824d90dChris Lattner  PatternLoc = SMLoc::getFromPointer(PatternStr.data());
1557112c86fc208145334aaa04812c794ce6feef416Mikhail Glushenkov
156a29703e8426763fa5232f9a91e6a5fce4d4244d6Chris Lattner  // Ignore trailing whitespace.
157a29703e8426763fa5232f9a91e6a5fce4d4244d6Chris Lattner  while (!PatternStr.empty() &&
158a29703e8426763fa5232f9a91e6a5fce4d4244d6Chris Lattner         (PatternStr.back() == ' ' || PatternStr.back() == '\t'))
159a29703e8426763fa5232f9a91e6a5fce4d4244d6Chris Lattner    PatternStr = PatternStr.substr(0, PatternStr.size()-1);
1607112c86fc208145334aaa04812c794ce6feef416Mikhail Glushenkov
161a29703e8426763fa5232f9a91e6a5fce4d4244d6Chris Lattner  // Check that there is something on the line.
162a29703e8426763fa5232f9a91e6a5fce4d4244d6Chris Lattner  if (PatternStr.empty()) {
1633f2d5f60b31fd057c10f77b2e607b23a8c94f6d3Chris Lattner    SM.PrintMessage(PatternLoc, SourceMgr::DK_Error,
1643f2d5f60b31fd057c10f77b2e607b23a8c94f6d3Chris Lattner                    "found empty check string with prefix '" +
1653f2d5f60b31fd057c10f77b2e607b23a8c94f6d3Chris Lattner                    CheckPrefix+":'");
166a29703e8426763fa5232f9a91e6a5fce4d4244d6Chris Lattner    return true;
167a29703e8426763fa5232f9a91e6a5fce4d4244d6Chris Lattner  }
1687112c86fc208145334aaa04812c794ce6feef416Mikhail Glushenkov
1692702e6aa53f603b20c3e46364bc1756788bd291aChris Lattner  // Check to see if this is a fixed string, or if it has regex pieces.
1704f50517577bb74fb4d2a18ad613fd05aa48f564dTed Kremenek  if (PatternStr.size() < 2 ||
171eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner      (PatternStr.find("{{") == StringRef::npos &&
172eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner       PatternStr.find("[[") == StringRef::npos)) {
1732702e6aa53f603b20c3e46364bc1756788bd291aChris Lattner    FixedStr = PatternStr;
1742702e6aa53f603b20c3e46364bc1756788bd291aChris Lattner    return false;
1752702e6aa53f603b20c3e46364bc1756788bd291aChris Lattner  }
1767112c86fc208145334aaa04812c794ce6feef416Mikhail Glushenkov
177eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner  // Paren value #0 is for the fully matched string.  Any new parenthesized
17813a38c4cb4c90a6d2b5313a6517d6291cb924730Chris Lattner  // values add from there.
179eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner  unsigned CurParen = 1;
1807112c86fc208145334aaa04812c794ce6feef416Mikhail Glushenkov
1815d6a05f4d4faea0c0c96fbf2bb57655df2839b34Chris Lattner  // Otherwise, there is at least one regex piece.  Build up the regex pattern
1825d6a05f4d4faea0c0c96fbf2bb57655df2839b34Chris Lattner  // by escaping scary characters in fixed strings, building up one big regex.
183528700863adefca8de461ce28a7d903729fb96b4Chris Lattner  while (!PatternStr.empty()) {
184eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner    // RegEx matches.
18513a38c4cb4c90a6d2b5313a6517d6291cb924730Chris Lattner    if (PatternStr.startswith("{{")) {
1861e5cbcb10adaca5c80121293b6c414d9285ebceeEli Bendersky      // This is the start of a regex match.  Scan for the }}.
187eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner      size_t End = PatternStr.find("}}");
188eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner      if (End == StringRef::npos) {
189eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner        SM.PrintMessage(SMLoc::getFromPointer(PatternStr.data()),
1903f2d5f60b31fd057c10f77b2e607b23a8c94f6d3Chris Lattner                        SourceMgr::DK_Error,
1913f2d5f60b31fd057c10f77b2e607b23a8c94f6d3Chris Lattner                        "found start of regex string with no end '}}'");
192eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner        return true;
193eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner      }
1947112c86fc208145334aaa04812c794ce6feef416Mikhail Glushenkov
19542e31dfd4f3c7fe8f83c930cd3a1700cef6914eaChris Lattner      // Enclose {{}} patterns in parens just like [[]] even though we're not
19642e31dfd4f3c7fe8f83c930cd3a1700cef6914eaChris Lattner      // capturing the result for any purpose.  This is required in case the
19742e31dfd4f3c7fe8f83c930cd3a1700cef6914eaChris Lattner      // expression contains an alternation like: CHECK:  abc{{x|z}}def.  We
19842e31dfd4f3c7fe8f83c930cd3a1700cef6914eaChris Lattner      // want this to turn into: "abc(x|z)def" not "abcx|zdef".
19942e31dfd4f3c7fe8f83c930cd3a1700cef6914eaChris Lattner      RegExStr += '(';
20042e31dfd4f3c7fe8f83c930cd3a1700cef6914eaChris Lattner      ++CurParen;
20142e31dfd4f3c7fe8f83c930cd3a1700cef6914eaChris Lattner
202eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner      if (AddRegExToRegEx(PatternStr.substr(2, End-2), CurParen, SM))
203eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner        return true;
20442e31dfd4f3c7fe8f83c930cd3a1700cef6914eaChris Lattner      RegExStr += ')';
20513a38c4cb4c90a6d2b5313a6517d6291cb924730Chris Lattner
206eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner      PatternStr = PatternStr.substr(End+2);
207528700863adefca8de461ce28a7d903729fb96b4Chris Lattner      continue;
208528700863adefca8de461ce28a7d903729fb96b4Chris Lattner    }
2097112c86fc208145334aaa04812c794ce6feef416Mikhail Glushenkov
210eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner    // Named RegEx matches.  These are of two forms: [[foo:.*]] which matches .*
211eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner    // (or some other regex) and assigns it to the FileCheck variable 'foo'. The
212eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner    // second form is [[foo]] which is a reference to foo.  The variable name
213964ac012017451ff24c33e6b749ec3223e1d291aDaniel Dunbar    // itself must be of the form "[a-zA-Z_][0-9a-zA-Z_]*", otherwise we reject
214eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner    // it.  This is to catch some common errors.
21513a38c4cb4c90a6d2b5313a6517d6291cb924730Chris Lattner    if (PatternStr.startswith("[[")) {
2164db6511779e70780f7b36bb7ef54276752f5f640Eli Bendersky      // Find the closing bracket pair ending the match.  End is going to be an
2174db6511779e70780f7b36bb7ef54276752f5f640Eli Bendersky      // offset relative to the beginning of the match string.
2184db6511779e70780f7b36bb7ef54276752f5f640Eli Bendersky      size_t End = FindRegexVarEnd(PatternStr.substr(2));
2194db6511779e70780f7b36bb7ef54276752f5f640Eli Bendersky
220eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner      if (End == StringRef::npos) {
221eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner        SM.PrintMessage(SMLoc::getFromPointer(PatternStr.data()),
2223f2d5f60b31fd057c10f77b2e607b23a8c94f6d3Chris Lattner                        SourceMgr::DK_Error,
2233f2d5f60b31fd057c10f77b2e607b23a8c94f6d3Chris Lattner                        "invalid named regex reference, no ]] found");
224eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner        return true;
225eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner      }
2267112c86fc208145334aaa04812c794ce6feef416Mikhail Glushenkov
2274db6511779e70780f7b36bb7ef54276752f5f640Eli Bendersky      StringRef MatchStr = PatternStr.substr(2, End);
2284db6511779e70780f7b36bb7ef54276752f5f640Eli Bendersky      PatternStr = PatternStr.substr(End+4);
2297112c86fc208145334aaa04812c794ce6feef416Mikhail Glushenkov
230eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner      // Get the regex name (e.g. "foo").
231eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner      size_t NameEnd = MatchStr.find(':');
232eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner      StringRef Name = MatchStr.substr(0, NameEnd);
2337112c86fc208145334aaa04812c794ce6feef416Mikhail Glushenkov
234eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner      if (Name.empty()) {
2353f2d5f60b31fd057c10f77b2e607b23a8c94f6d3Chris Lattner        SM.PrintMessage(SMLoc::getFromPointer(Name.data()), SourceMgr::DK_Error,
2363f2d5f60b31fd057c10f77b2e607b23a8c94f6d3Chris Lattner                        "invalid name in named regex: empty name");
237eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner        return true;
238eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner      }
239eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner
24070a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko      // Verify that the name/expression is well formed. FileCheck currently
24170a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko      // supports @LINE, @LINE+number, @LINE-number expressions. The check here
24270a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko      // is relaxed, more strict check is performed in \c EvaluateExpression.
24370a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko      bool IsExpression = false;
24470a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko      for (unsigned i = 0, e = Name.size(); i != e; ++i) {
24570a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko        if (i == 0 && Name[i] == '@') {
24670a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko          if (NameEnd != StringRef::npos) {
24770a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko            SM.PrintMessage(SMLoc::getFromPointer(Name.data()),
24870a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko                            SourceMgr::DK_Error,
24970a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko                            "invalid name in named regex definition");
25070a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko            return true;
25170a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko          }
25270a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko          IsExpression = true;
25370a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko          continue;
25470a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko        }
25570a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko        if (Name[i] != '_' && !isalnum(Name[i]) &&
25670a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko            (!IsExpression || (Name[i] != '+' && Name[i] != '-'))) {
257eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner          SM.PrintMessage(SMLoc::getFromPointer(Name.data()+i),
2583f2d5f60b31fd057c10f77b2e607b23a8c94f6d3Chris Lattner                          SourceMgr::DK_Error, "invalid name in named regex");
259eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner          return true;
260eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner        }
26170a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko      }
2627112c86fc208145334aaa04812c794ce6feef416Mikhail Glushenkov
263eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner      // Name can't start with a digit.
26487d0b9ed1462705dd9bf1cb7f67d0bf03af776c8Guy Benyei      if (isdigit(static_cast<unsigned char>(Name[0]))) {
2653f2d5f60b31fd057c10f77b2e607b23a8c94f6d3Chris Lattner        SM.PrintMessage(SMLoc::getFromPointer(Name.data()), SourceMgr::DK_Error,
2663f2d5f60b31fd057c10f77b2e607b23a8c94f6d3Chris Lattner                        "invalid name in named regex");
267eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner        return true;
268eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner      }
2697112c86fc208145334aaa04812c794ce6feef416Mikhail Glushenkov
270eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner      // Handle [[foo]].
271eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner      if (NameEnd == StringRef::npos) {
2729756ca7ba0c7f6c3b1e76ee12ca27ddca04be9d7Eli Bendersky        // Handle variables that were defined earlier on the same line by
2739756ca7ba0c7f6c3b1e76ee12ca27ddca04be9d7Eli Bendersky        // emitting a backreference.
2749756ca7ba0c7f6c3b1e76ee12ca27ddca04be9d7Eli Bendersky        if (VariableDefs.find(Name) != VariableDefs.end()) {
2759756ca7ba0c7f6c3b1e76ee12ca27ddca04be9d7Eli Bendersky          unsigned VarParenNum = VariableDefs[Name];
2769756ca7ba0c7f6c3b1e76ee12ca27ddca04be9d7Eli Bendersky          if (VarParenNum < 1 || VarParenNum > 9) {
2779756ca7ba0c7f6c3b1e76ee12ca27ddca04be9d7Eli Bendersky            SM.PrintMessage(SMLoc::getFromPointer(Name.data()),
2789756ca7ba0c7f6c3b1e76ee12ca27ddca04be9d7Eli Bendersky                            SourceMgr::DK_Error,
2799756ca7ba0c7f6c3b1e76ee12ca27ddca04be9d7Eli Bendersky                            "Can't back-reference more than 9 variables");
2809756ca7ba0c7f6c3b1e76ee12ca27ddca04be9d7Eli Bendersky            return true;
2819756ca7ba0c7f6c3b1e76ee12ca27ddca04be9d7Eli Bendersky          }
2829756ca7ba0c7f6c3b1e76ee12ca27ddca04be9d7Eli Bendersky          AddBackrefToRegEx(VarParenNum);
2839756ca7ba0c7f6c3b1e76ee12ca27ddca04be9d7Eli Bendersky        } else {
2849756ca7ba0c7f6c3b1e76ee12ca27ddca04be9d7Eli Bendersky          VariableUses.push_back(std::make_pair(Name, RegExStr.size()));
2859756ca7ba0c7f6c3b1e76ee12ca27ddca04be9d7Eli Bendersky        }
286eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner        continue;
287eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner      }
2887112c86fc208145334aaa04812c794ce6feef416Mikhail Glushenkov
289eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner      // Handle [[foo:.*]].
2909756ca7ba0c7f6c3b1e76ee12ca27ddca04be9d7Eli Bendersky      VariableDefs[Name] = CurParen;
291eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner      RegExStr += '(';
292eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner      ++CurParen;
2937112c86fc208145334aaa04812c794ce6feef416Mikhail Glushenkov
294eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner      if (AddRegExToRegEx(MatchStr.substr(NameEnd+1), CurParen, SM))
295eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner        return true;
296eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner
297eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner      RegExStr += ')';
298528700863adefca8de461ce28a7d903729fb96b4Chris Lattner    }
2997112c86fc208145334aaa04812c794ce6feef416Mikhail Glushenkov
300eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner    // Handle fixed string matches.
301eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner    // Find the end, which is the start of the next regex.
302eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner    size_t FixedMatchEnd = PatternStr.find("{{");
303eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner    FixedMatchEnd = std::min(FixedMatchEnd, PatternStr.find("[["));
304eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner    AddFixedStringToRegEx(PatternStr.substr(0, FixedMatchEnd), RegExStr);
305eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner    PatternStr = PatternStr.substr(FixedMatchEnd);
306528700863adefca8de461ce28a7d903729fb96b4Chris Lattner  }
307528700863adefca8de461ce28a7d903729fb96b4Chris Lattner
308528700863adefca8de461ce28a7d903729fb96b4Chris Lattner  return false;
309528700863adefca8de461ce28a7d903729fb96b4Chris Lattner}
310adea46ed617982ea07fc3266d52717496c0076ceChris Lattner
311eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattnervoid Pattern::AddFixedStringToRegEx(StringRef FixedStr, std::string &TheStr) {
3125d6a05f4d4faea0c0c96fbf2bb57655df2839b34Chris Lattner  // Add the characters from FixedStr to the regex, escaping as needed.  This
3135d6a05f4d4faea0c0c96fbf2bb57655df2839b34Chris Lattner  // avoids "leaning toothpicks" in common patterns.
3145d6a05f4d4faea0c0c96fbf2bb57655df2839b34Chris Lattner  for (unsigned i = 0, e = FixedStr.size(); i != e; ++i) {
3155d6a05f4d4faea0c0c96fbf2bb57655df2839b34Chris Lattner    switch (FixedStr[i]) {
3165d6a05f4d4faea0c0c96fbf2bb57655df2839b34Chris Lattner    // These are the special characters matched in "p_ere_exp".
3175d6a05f4d4faea0c0c96fbf2bb57655df2839b34Chris Lattner    case '(':
3185d6a05f4d4faea0c0c96fbf2bb57655df2839b34Chris Lattner    case ')':
3195d6a05f4d4faea0c0c96fbf2bb57655df2839b34Chris Lattner    case '^':
3205d6a05f4d4faea0c0c96fbf2bb57655df2839b34Chris Lattner    case '$':
3215d6a05f4d4faea0c0c96fbf2bb57655df2839b34Chris Lattner    case '|':
3225d6a05f4d4faea0c0c96fbf2bb57655df2839b34Chris Lattner    case '*':
3235d6a05f4d4faea0c0c96fbf2bb57655df2839b34Chris Lattner    case '+':
3245d6a05f4d4faea0c0c96fbf2bb57655df2839b34Chris Lattner    case '?':
3255d6a05f4d4faea0c0c96fbf2bb57655df2839b34Chris Lattner    case '.':
3265d6a05f4d4faea0c0c96fbf2bb57655df2839b34Chris Lattner    case '[':
3275d6a05f4d4faea0c0c96fbf2bb57655df2839b34Chris Lattner    case '\\':
3285d6a05f4d4faea0c0c96fbf2bb57655df2839b34Chris Lattner    case '{':
329eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner      TheStr += '\\';
3305d6a05f4d4faea0c0c96fbf2bb57655df2839b34Chris Lattner      // FALL THROUGH.
3315d6a05f4d4faea0c0c96fbf2bb57655df2839b34Chris Lattner    default:
332eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner      TheStr += FixedStr[i];
3335d6a05f4d4faea0c0c96fbf2bb57655df2839b34Chris Lattner      break;
3345d6a05f4d4faea0c0c96fbf2bb57655df2839b34Chris Lattner    }
3355d6a05f4d4faea0c0c96fbf2bb57655df2839b34Chris Lattner  }
3365d6a05f4d4faea0c0c96fbf2bb57655df2839b34Chris Lattner}
3375d6a05f4d4faea0c0c96fbf2bb57655df2839b34Chris Lattner
3389756ca7ba0c7f6c3b1e76ee12ca27ddca04be9d7Eli Benderskybool Pattern::AddRegExToRegEx(StringRef RS, unsigned &CurParen,
339eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner                              SourceMgr &SM) {
3409756ca7ba0c7f6c3b1e76ee12ca27ddca04be9d7Eli Bendersky  Regex R(RS);
341eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner  std::string Error;
342eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner  if (!R.isValid(Error)) {
3439756ca7ba0c7f6c3b1e76ee12ca27ddca04be9d7Eli Bendersky    SM.PrintMessage(SMLoc::getFromPointer(RS.data()), SourceMgr::DK_Error,
3443f2d5f60b31fd057c10f77b2e607b23a8c94f6d3Chris Lattner                    "invalid regex: " + Error);
345eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner    return true;
346eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner  }
3477112c86fc208145334aaa04812c794ce6feef416Mikhail Glushenkov
3489756ca7ba0c7f6c3b1e76ee12ca27ddca04be9d7Eli Bendersky  RegExStr += RS.str();
349eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner  CurParen += R.getNumMatches();
350eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner  return false;
351eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner}
3525d6a05f4d4faea0c0c96fbf2bb57655df2839b34Chris Lattner
3539756ca7ba0c7f6c3b1e76ee12ca27ddca04be9d7Eli Benderskyvoid Pattern::AddBackrefToRegEx(unsigned BackrefNum) {
3549756ca7ba0c7f6c3b1e76ee12ca27ddca04be9d7Eli Bendersky  assert(BackrefNum >= 1 && BackrefNum <= 9 && "Invalid backref number");
3559756ca7ba0c7f6c3b1e76ee12ca27ddca04be9d7Eli Bendersky  std::string Backref = std::string("\\") +
3569756ca7ba0c7f6c3b1e76ee12ca27ddca04be9d7Eli Bendersky                        std::string(1, '0' + BackrefNum);
3579756ca7ba0c7f6c3b1e76ee12ca27ddca04be9d7Eli Bendersky  RegExStr += Backref;
3589756ca7ba0c7f6c3b1e76ee12ca27ddca04be9d7Eli Bendersky}
3599756ca7ba0c7f6c3b1e76ee12ca27ddca04be9d7Eli Bendersky
36070a870add82dab944b98ee1840fafff33795fc95Alexander Kornienkobool Pattern::EvaluateExpression(StringRef Expr, std::string &Value) const {
36170a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko  // The only supported expression is @LINE([\+-]\d+)?
36270a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko  if (!Expr.startswith("@LINE"))
36370a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko    return false;
36470a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko  Expr = Expr.substr(StringRef("@LINE").size());
36570a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko  int Offset = 0;
36670a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko  if (!Expr.empty()) {
36770a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko    if (Expr[0] == '+')
36870a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko      Expr = Expr.substr(1);
36970a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko    else if (Expr[0] != '-')
37070a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko      return false;
37170a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko    if (Expr.getAsInteger(10, Offset))
37270a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko      return false;
37370a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko  }
37470a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko  Value = llvm::itostr(LineNumber + Offset);
37570a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko  return true;
37670a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko}
37770a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko
378528700863adefca8de461ce28a7d903729fb96b4Chris Lattner/// Match - Match the pattern string against the input buffer Buffer.  This
379528700863adefca8de461ce28a7d903729fb96b4Chris Lattner/// returns the position that is matched or npos if there is no match.  If
380528700863adefca8de461ce28a7d903729fb96b4Chris Lattner/// there is a match, the size of the matched string is returned in MatchLen.
381eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattnersize_t Pattern::Match(StringRef Buffer, size_t &MatchLen,
382eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner                      StringMap<StringRef> &VariableTable) const {
383824c10ece26fd031591b1770acc8a6c2575a3ab8Jakob Stoklund Olesen  // If this is the EOF pattern, match it immediately.
384824c10ece26fd031591b1770acc8a6c2575a3ab8Jakob Stoklund Olesen  if (MatchEOF) {
385824c10ece26fd031591b1770acc8a6c2575a3ab8Jakob Stoklund Olesen    MatchLen = 0;
386824c10ece26fd031591b1770acc8a6c2575a3ab8Jakob Stoklund Olesen    return Buffer.size();
387824c10ece26fd031591b1770acc8a6c2575a3ab8Jakob Stoklund Olesen  }
388824c10ece26fd031591b1770acc8a6c2575a3ab8Jakob Stoklund Olesen
3892702e6aa53f603b20c3e46364bc1756788bd291aChris Lattner  // If this is a fixed string pattern, just match it now.
3902702e6aa53f603b20c3e46364bc1756788bd291aChris Lattner  if (!FixedStr.empty()) {
3912702e6aa53f603b20c3e46364bc1756788bd291aChris Lattner    MatchLen = FixedStr.size();
3922702e6aa53f603b20c3e46364bc1756788bd291aChris Lattner    return Buffer.find(FixedStr);
3932702e6aa53f603b20c3e46364bc1756788bd291aChris Lattner  }
394eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner
3955d6a05f4d4faea0c0c96fbf2bb57655df2839b34Chris Lattner  // Regex match.
3967112c86fc208145334aaa04812c794ce6feef416Mikhail Glushenkov
397eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner  // If there are variable uses, we need to create a temporary string with the
398eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner  // actual value.
399eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner  StringRef RegExToMatch = RegExStr;
400eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner  std::string TmpStr;
401eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner  if (!VariableUses.empty()) {
402eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner    TmpStr = RegExStr;
4037112c86fc208145334aaa04812c794ce6feef416Mikhail Glushenkov
404eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner    unsigned InsertOffset = 0;
405eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner    for (unsigned i = 0, e = VariableUses.size(); i != e; ++i) {
406eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner      std::string Value;
40770a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko
40870a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko      if (VariableUses[i].first[0] == '@') {
40970a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko        if (!EvaluateExpression(VariableUses[i].first, Value))
41070a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko          return StringRef::npos;
41170a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko      } else {
41270a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko        StringMap<StringRef>::iterator it =
41370a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko          VariableTable.find(VariableUses[i].first);
41470a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko        // If the variable is undefined, return an error.
41570a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko        if (it == VariableTable.end())
41670a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko          return StringRef::npos;
41770a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko
41870a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko        // Look up the value and escape it so that we can plop it into the regex.
41970a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko        AddFixedStringToRegEx(it->second, Value);
42070a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko      }
4217112c86fc208145334aaa04812c794ce6feef416Mikhail Glushenkov
422eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner      // Plop it into the regex at the adjusted offset.
423eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner      TmpStr.insert(TmpStr.begin()+VariableUses[i].second+InsertOffset,
424eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner                    Value.begin(), Value.end());
425eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner      InsertOffset += Value.size();
426eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner    }
4277112c86fc208145334aaa04812c794ce6feef416Mikhail Glushenkov
428eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner    // Match the newly constructed regex.
429eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner    RegExToMatch = TmpStr;
430eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner  }
4317112c86fc208145334aaa04812c794ce6feef416Mikhail Glushenkov
4327112c86fc208145334aaa04812c794ce6feef416Mikhail Glushenkov
4335d6a05f4d4faea0c0c96fbf2bb57655df2839b34Chris Lattner  SmallVector<StringRef, 4> MatchInfo;
434eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner  if (!Regex(RegExToMatch, Regex::Newline).match(Buffer, &MatchInfo))
4355d6a05f4d4faea0c0c96fbf2bb57655df2839b34Chris Lattner    return StringRef::npos;
4367112c86fc208145334aaa04812c794ce6feef416Mikhail Glushenkov
4375d6a05f4d4faea0c0c96fbf2bb57655df2839b34Chris Lattner  // Successful regex match.
4385d6a05f4d4faea0c0c96fbf2bb57655df2839b34Chris Lattner  assert(!MatchInfo.empty() && "Didn't get any match");
4395d6a05f4d4faea0c0c96fbf2bb57655df2839b34Chris Lattner  StringRef FullMatch = MatchInfo[0];
4407112c86fc208145334aaa04812c794ce6feef416Mikhail Glushenkov
441eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner  // If this defines any variables, remember their values.
4429756ca7ba0c7f6c3b1e76ee12ca27ddca04be9d7Eli Bendersky  for (std::map<StringRef, unsigned>::const_iterator I = VariableDefs.begin(),
4439756ca7ba0c7f6c3b1e76ee12ca27ddca04be9d7Eli Bendersky                                                     E = VariableDefs.end();
4449756ca7ba0c7f6c3b1e76ee12ca27ddca04be9d7Eli Bendersky       I != E; ++I) {
4459756ca7ba0c7f6c3b1e76ee12ca27ddca04be9d7Eli Bendersky    assert(I->second < MatchInfo.size() && "Internal paren error");
4469756ca7ba0c7f6c3b1e76ee12ca27ddca04be9d7Eli Bendersky    VariableTable[I->first] = MatchInfo[I->second];
44794638f0081b6ec8c7cc5ad9fec8ddbdd6824d90dChris Lattner  }
4487112c86fc208145334aaa04812c794ce6feef416Mikhail Glushenkov
4495d6a05f4d4faea0c0c96fbf2bb57655df2839b34Chris Lattner  MatchLen = FullMatch.size();
4505d6a05f4d4faea0c0c96fbf2bb57655df2839b34Chris Lattner  return FullMatch.data()-Buffer.data();
451a29703e8426763fa5232f9a91e6a5fce4d4244d6Chris Lattner}
452a29703e8426763fa5232f9a91e6a5fce4d4244d6Chris Lattner
453ead2dacc9ee028906cb104c8c3d66ccbbebe6b10Daniel Dunbarunsigned Pattern::ComputeMatchDistance(StringRef Buffer,
454ead2dacc9ee028906cb104c8c3d66ccbbebe6b10Daniel Dunbar                              const StringMap<StringRef> &VariableTable) const {
455ead2dacc9ee028906cb104c8c3d66ccbbebe6b10Daniel Dunbar  // Just compute the number of matching characters. For regular expressions, we
456ead2dacc9ee028906cb104c8c3d66ccbbebe6b10Daniel Dunbar  // just compare against the regex itself and hope for the best.
457ead2dacc9ee028906cb104c8c3d66ccbbebe6b10Daniel Dunbar  //
458ead2dacc9ee028906cb104c8c3d66ccbbebe6b10Daniel Dunbar  // FIXME: One easy improvement here is have the regex lib generate a single
459ead2dacc9ee028906cb104c8c3d66ccbbebe6b10Daniel Dunbar  // example regular expression which matches, and use that as the example
460ead2dacc9ee028906cb104c8c3d66ccbbebe6b10Daniel Dunbar  // string.
461ead2dacc9ee028906cb104c8c3d66ccbbebe6b10Daniel Dunbar  StringRef ExampleString(FixedStr);
462ead2dacc9ee028906cb104c8c3d66ccbbebe6b10Daniel Dunbar  if (ExampleString.empty())
463ead2dacc9ee028906cb104c8c3d66ccbbebe6b10Daniel Dunbar    ExampleString = RegExStr;
464ead2dacc9ee028906cb104c8c3d66ccbbebe6b10Daniel Dunbar
4650806f9ff5860ce351540ff2897dec1667154ca19Daniel Dunbar  // Only compare up to the first line in the buffer, or the string size.
4660806f9ff5860ce351540ff2897dec1667154ca19Daniel Dunbar  StringRef BufferPrefix = Buffer.substr(0, ExampleString.size());
4670806f9ff5860ce351540ff2897dec1667154ca19Daniel Dunbar  BufferPrefix = BufferPrefix.split('\n').first;
4680806f9ff5860ce351540ff2897dec1667154ca19Daniel Dunbar  return BufferPrefix.edit_distance(ExampleString);
469ead2dacc9ee028906cb104c8c3d66ccbbebe6b10Daniel Dunbar}
470ead2dacc9ee028906cb104c8c3d66ccbbebe6b10Daniel Dunbar
471fafe93c8bcbc538573bc5e890f24f9869a11f846Daniel Dunbarvoid Pattern::PrintFailureInfo(const SourceMgr &SM, StringRef Buffer,
472fafe93c8bcbc538573bc5e890f24f9869a11f846Daniel Dunbar                               const StringMap<StringRef> &VariableTable) const{
473fafe93c8bcbc538573bc5e890f24f9869a11f846Daniel Dunbar  // If this was a regular expression using variables, print the current
474fafe93c8bcbc538573bc5e890f24f9869a11f846Daniel Dunbar  // variable values.
475fafe93c8bcbc538573bc5e890f24f9869a11f846Daniel Dunbar  if (!VariableUses.empty()) {
476fafe93c8bcbc538573bc5e890f24f9869a11f846Daniel Dunbar    for (unsigned i = 0, e = VariableUses.size(); i != e; ++i) {
477fafe93c8bcbc538573bc5e890f24f9869a11f846Daniel Dunbar      SmallString<256> Msg;
478fafe93c8bcbc538573bc5e890f24f9869a11f846Daniel Dunbar      raw_svector_ostream OS(Msg);
47970a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko      StringRef Var = VariableUses[i].first;
48070a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko      if (Var[0] == '@') {
48170a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko        std::string Value;
48270a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko        if (EvaluateExpression(Var, Value)) {
48370a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko          OS << "with expression \"";
48470a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko          OS.write_escaped(Var) << "\" equal to \"";
48570a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko          OS.write_escaped(Value) << "\"";
48670a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko        } else {
48770a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko          OS << "uses incorrect expression \"";
48870a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko          OS.write_escaped(Var) << "\"";
48970a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko        }
490fafe93c8bcbc538573bc5e890f24f9869a11f846Daniel Dunbar      } else {
49170a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko        StringMap<StringRef>::const_iterator it = VariableTable.find(Var);
49270a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko
49370a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko        // Check for undefined variable references.
49470a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko        if (it == VariableTable.end()) {
49570a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko          OS << "uses undefined variable \"";
49670a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko          OS.write_escaped(Var) << "\"";
49770a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko        } else {
49870a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko          OS << "with variable \"";
49970a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko          OS.write_escaped(Var) << "\" equal to \"";
50070a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko          OS.write_escaped(it->second) << "\"";
50170a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko        }
502fafe93c8bcbc538573bc5e890f24f9869a11f846Daniel Dunbar      }
503fafe93c8bcbc538573bc5e890f24f9869a11f846Daniel Dunbar
5043f2d5f60b31fd057c10f77b2e607b23a8c94f6d3Chris Lattner      SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note,
5053f2d5f60b31fd057c10f77b2e607b23a8c94f6d3Chris Lattner                      OS.str());
506fafe93c8bcbc538573bc5e890f24f9869a11f846Daniel Dunbar    }
507fafe93c8bcbc538573bc5e890f24f9869a11f846Daniel Dunbar  }
508ead2dacc9ee028906cb104c8c3d66ccbbebe6b10Daniel Dunbar
509ead2dacc9ee028906cb104c8c3d66ccbbebe6b10Daniel Dunbar  // Attempt to find the closest/best fuzzy match.  Usually an error happens
510ead2dacc9ee028906cb104c8c3d66ccbbebe6b10Daniel Dunbar  // because some string in the output didn't exactly match. In these cases, we
511ead2dacc9ee028906cb104c8c3d66ccbbebe6b10Daniel Dunbar  // would like to show the user a best guess at what "should have" matched, to
512ead2dacc9ee028906cb104c8c3d66ccbbebe6b10Daniel Dunbar  // save them having to actually check the input manually.
513ead2dacc9ee028906cb104c8c3d66ccbbebe6b10Daniel Dunbar  size_t NumLinesForward = 0;
514ead2dacc9ee028906cb104c8c3d66ccbbebe6b10Daniel Dunbar  size_t Best = StringRef::npos;
515ead2dacc9ee028906cb104c8c3d66ccbbebe6b10Daniel Dunbar  double BestQuality = 0;
516ead2dacc9ee028906cb104c8c3d66ccbbebe6b10Daniel Dunbar
517ead2dacc9ee028906cb104c8c3d66ccbbebe6b10Daniel Dunbar  // Use an arbitrary 4k limit on how far we will search.
518e3a1e506809acbddceb6840914879c498d454f26Dan Gohman  for (size_t i = 0, e = std::min(size_t(4096), Buffer.size()); i != e; ++i) {
519ead2dacc9ee028906cb104c8c3d66ccbbebe6b10Daniel Dunbar    if (Buffer[i] == '\n')
520ead2dacc9ee028906cb104c8c3d66ccbbebe6b10Daniel Dunbar      ++NumLinesForward;
521ead2dacc9ee028906cb104c8c3d66ccbbebe6b10Daniel Dunbar
522d8a5541a513695039d1eb83eeced05d51ce9f567Dan Gohman    // Patterns have leading whitespace stripped, so skip whitespace when
523d8a5541a513695039d1eb83eeced05d51ce9f567Dan Gohman    // looking for something which looks like a pattern.
524d8a5541a513695039d1eb83eeced05d51ce9f567Dan Gohman    if (Buffer[i] == ' ' || Buffer[i] == '\t')
525d8a5541a513695039d1eb83eeced05d51ce9f567Dan Gohman      continue;
526d8a5541a513695039d1eb83eeced05d51ce9f567Dan Gohman
527ead2dacc9ee028906cb104c8c3d66ccbbebe6b10Daniel Dunbar    // Compute the "quality" of this match as an arbitrary combination of the
528ead2dacc9ee028906cb104c8c3d66ccbbebe6b10Daniel Dunbar    // match distance and the number of lines skipped to get to this match.
529ead2dacc9ee028906cb104c8c3d66ccbbebe6b10Daniel Dunbar    unsigned Distance = ComputeMatchDistance(Buffer.substr(i), VariableTable);
530ead2dacc9ee028906cb104c8c3d66ccbbebe6b10Daniel Dunbar    double Quality = Distance + (NumLinesForward / 100.);
531ead2dacc9ee028906cb104c8c3d66ccbbebe6b10Daniel Dunbar
532ead2dacc9ee028906cb104c8c3d66ccbbebe6b10Daniel Dunbar    if (Quality < BestQuality || Best == StringRef::npos) {
533ead2dacc9ee028906cb104c8c3d66ccbbebe6b10Daniel Dunbar      Best = i;
534ead2dacc9ee028906cb104c8c3d66ccbbebe6b10Daniel Dunbar      BestQuality = Quality;
535ead2dacc9ee028906cb104c8c3d66ccbbebe6b10Daniel Dunbar    }
536ead2dacc9ee028906cb104c8c3d66ccbbebe6b10Daniel Dunbar  }
537ead2dacc9ee028906cb104c8c3d66ccbbebe6b10Daniel Dunbar
5387a68e0df0d2eb46f509ef086729e46a0e79e4750Daniel Dunbar  // Print the "possible intended match here" line if we found something
5397a68e0df0d2eb46f509ef086729e46a0e79e4750Daniel Dunbar  // reasonable and not equal to what we showed in the "scanning from here"
5407a68e0df0d2eb46f509ef086729e46a0e79e4750Daniel Dunbar  // line.
5417a68e0df0d2eb46f509ef086729e46a0e79e4750Daniel Dunbar  if (Best && Best != StringRef::npos && BestQuality < 50) {
5427a68e0df0d2eb46f509ef086729e46a0e79e4750Daniel Dunbar      SM.PrintMessage(SMLoc::getFromPointer(Buffer.data() + Best),
5433f2d5f60b31fd057c10f77b2e607b23a8c94f6d3Chris Lattner                      SourceMgr::DK_Note, "possible intended match here");
544ead2dacc9ee028906cb104c8c3d66ccbbebe6b10Daniel Dunbar
545ead2dacc9ee028906cb104c8c3d66ccbbebe6b10Daniel Dunbar    // FIXME: If we wanted to be really friendly we would show why the match
546ead2dacc9ee028906cb104c8c3d66ccbbebe6b10Daniel Dunbar    // failed, as it can be hard to spot simple one character differences.
547ead2dacc9ee028906cb104c8c3d66ccbbebe6b10Daniel Dunbar  }
548fafe93c8bcbc538573bc5e890f24f9869a11f846Daniel Dunbar}
549a29703e8426763fa5232f9a91e6a5fce4d4244d6Chris Lattner
5504db6511779e70780f7b36bb7ef54276752f5f640Eli Benderskysize_t Pattern::FindRegexVarEnd(StringRef Str) {
5514db6511779e70780f7b36bb7ef54276752f5f640Eli Bendersky  // Offset keeps track of the current offset within the input Str
5524db6511779e70780f7b36bb7ef54276752f5f640Eli Bendersky  size_t Offset = 0;
5534db6511779e70780f7b36bb7ef54276752f5f640Eli Bendersky  // [...] Nesting depth
5544db6511779e70780f7b36bb7ef54276752f5f640Eli Bendersky  size_t BracketDepth = 0;
5554db6511779e70780f7b36bb7ef54276752f5f640Eli Bendersky
5564db6511779e70780f7b36bb7ef54276752f5f640Eli Bendersky  while (!Str.empty()) {
5574db6511779e70780f7b36bb7ef54276752f5f640Eli Bendersky    if (Str.startswith("]]") && BracketDepth == 0)
5584db6511779e70780f7b36bb7ef54276752f5f640Eli Bendersky      return Offset;
5594db6511779e70780f7b36bb7ef54276752f5f640Eli Bendersky    if (Str[0] == '\\') {
5604db6511779e70780f7b36bb7ef54276752f5f640Eli Bendersky      // Backslash escapes the next char within regexes, so skip them both.
5614db6511779e70780f7b36bb7ef54276752f5f640Eli Bendersky      Str = Str.substr(2);
5624db6511779e70780f7b36bb7ef54276752f5f640Eli Bendersky      Offset += 2;
5634db6511779e70780f7b36bb7ef54276752f5f640Eli Bendersky    } else {
5644db6511779e70780f7b36bb7ef54276752f5f640Eli Bendersky      switch (Str[0]) {
5654db6511779e70780f7b36bb7ef54276752f5f640Eli Bendersky        default:
5664db6511779e70780f7b36bb7ef54276752f5f640Eli Bendersky          break;
5674db6511779e70780f7b36bb7ef54276752f5f640Eli Bendersky        case '[':
5684db6511779e70780f7b36bb7ef54276752f5f640Eli Bendersky          BracketDepth++;
5694db6511779e70780f7b36bb7ef54276752f5f640Eli Bendersky          break;
5704db6511779e70780f7b36bb7ef54276752f5f640Eli Bendersky        case ']':
5714db6511779e70780f7b36bb7ef54276752f5f640Eli Bendersky          assert(BracketDepth > 0 && "Invalid regex");
5724db6511779e70780f7b36bb7ef54276752f5f640Eli Bendersky          BracketDepth--;
5734db6511779e70780f7b36bb7ef54276752f5f640Eli Bendersky          break;
5744db6511779e70780f7b36bb7ef54276752f5f640Eli Bendersky      }
5754db6511779e70780f7b36bb7ef54276752f5f640Eli Bendersky      Str = Str.substr(1);
5764db6511779e70780f7b36bb7ef54276752f5f640Eli Bendersky      Offset++;
5774db6511779e70780f7b36bb7ef54276752f5f640Eli Bendersky    }
5784db6511779e70780f7b36bb7ef54276752f5f640Eli Bendersky  }
5794db6511779e70780f7b36bb7ef54276752f5f640Eli Bendersky
5804db6511779e70780f7b36bb7ef54276752f5f640Eli Bendersky  return StringRef::npos;
5814db6511779e70780f7b36bb7ef54276752f5f640Eli Bendersky}
5824db6511779e70780f7b36bb7ef54276752f5f640Eli Bendersky
5834db6511779e70780f7b36bb7ef54276752f5f640Eli Bendersky
584a29703e8426763fa5232f9a91e6a5fce4d4244d6Chris Lattner//===----------------------------------------------------------------------===//
585a29703e8426763fa5232f9a91e6a5fce4d4244d6Chris Lattner// Check Strings.
586a29703e8426763fa5232f9a91e6a5fce4d4244d6Chris Lattner//===----------------------------------------------------------------------===//
5879fc6678bea11f32acba4e9b6624ae9a0d3a9287bChris Lattner
5889fc6678bea11f32acba4e9b6624ae9a0d3a9287bChris Lattner/// CheckString - This is a check that we found in the input file.
5899fc6678bea11f32acba4e9b6624ae9a0d3a9287bChris Lattnerstruct CheckString {
5909fc6678bea11f32acba4e9b6624ae9a0d3a9287bChris Lattner  /// Pat - The pattern to match.
5919fc6678bea11f32acba4e9b6624ae9a0d3a9287bChris Lattner  Pattern Pat;
5927112c86fc208145334aaa04812c794ce6feef416Mikhail Glushenkov
593207e1bcf897d1c732f717b9773029651ecc59ab2Chris Lattner  /// Loc - The location in the match file that the check string was specified.
594207e1bcf897d1c732f717b9773029651ecc59ab2Chris Lattner  SMLoc Loc;
5957112c86fc208145334aaa04812c794ce6feef416Mikhail Glushenkov
5965dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner  /// IsCheckNext - This is true if this is a CHECK-NEXT: directive (as opposed
5975dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner  /// to a CHECK: directive.
5985dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner  bool IsCheckNext;
5997112c86fc208145334aaa04812c794ce6feef416Mikhail Glushenkov
600178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin  /// IsCheckLabel - This is true if this is a CHECK-LABEL: directive (as
601178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin  /// opposed to a CHECK: directive.
602178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin  bool IsCheckLabel;
603178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin
60495ab32667456b13ad56634cc7554cde8a50db95aMichael Liao  /// DagNotStrings - These are all of the strings that are disallowed from
605f15380ba8ae35941dcd56d9a288ad023295dde30Chris Lattner  /// occurring between this match string and the previous one (or start of
606f15380ba8ae35941dcd56d9a288ad023295dde30Chris Lattner  /// file).
60795ab32667456b13ad56634cc7554cde8a50db95aMichael Liao  std::vector<Pattern> DagNotStrings;
6087112c86fc208145334aaa04812c794ce6feef416Mikhail Glushenkov
609178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin  CheckString(const Pattern &P, SMLoc L, bool isCheckNext, bool isCheckLabel)
610178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin    : Pat(P), Loc(L), IsCheckNext(isCheckNext), IsCheckLabel(isCheckLabel) {}
6117efbbd61eb0aa85ec189db8f02c85ad9078946e9Michael Liao
61295ab32667456b13ad56634cc7554cde8a50db95aMichael Liao  /// Check - Match check string and its "not strings" and/or "dag strings".
613178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin  size_t Check(const SourceMgr &SM, StringRef Buffer, bool IsLabel,
614178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin               size_t &MatchLen, StringMap<StringRef> &VariableTable) const;
6157efbbd61eb0aa85ec189db8f02c85ad9078946e9Michael Liao
6167efbbd61eb0aa85ec189db8f02c85ad9078946e9Michael Liao  /// CheckNext - Verify there is a single line in the given buffer.
6177efbbd61eb0aa85ec189db8f02c85ad9078946e9Michael Liao  bool CheckNext(const SourceMgr &SM, StringRef Buffer) const;
6187efbbd61eb0aa85ec189db8f02c85ad9078946e9Michael Liao
6197efbbd61eb0aa85ec189db8f02c85ad9078946e9Michael Liao  /// CheckNot - Verify there's no "not strings" in the given buffer.
6207efbbd61eb0aa85ec189db8f02c85ad9078946e9Michael Liao  bool CheckNot(const SourceMgr &SM, StringRef Buffer,
62195ab32667456b13ad56634cc7554cde8a50db95aMichael Liao                const std::vector<const Pattern *> &NotStrings,
6227efbbd61eb0aa85ec189db8f02c85ad9078946e9Michael Liao                StringMap<StringRef> &VariableTable) const;
62395ab32667456b13ad56634cc7554cde8a50db95aMichael Liao
62495ab32667456b13ad56634cc7554cde8a50db95aMichael Liao  /// CheckDag - Match "dag strings" and their mixed "not strings".
62595ab32667456b13ad56634cc7554cde8a50db95aMichael Liao  size_t CheckDag(const SourceMgr &SM, StringRef Buffer,
62695ab32667456b13ad56634cc7554cde8a50db95aMichael Liao                  std::vector<const Pattern *> &NotStrings,
62795ab32667456b13ad56634cc7554cde8a50db95aMichael Liao                  StringMap<StringRef> &VariableTable) const;
628207e1bcf897d1c732f717b9773029651ecc59ab2Chris Lattner};
629207e1bcf897d1c732f717b9773029651ecc59ab2Chris Lattner
6304cc74fcba06ce43ee325510dc6137bd050f96c68Guy Benyei/// Canonicalize whitespaces in the input file. Line endings are replaced
6314cc74fcba06ce43ee325510dc6137bd050f96c68Guy Benyei/// with UNIX-style '\n'.
6324cc74fcba06ce43ee325510dc6137bd050f96c68Guy Benyei///
6334cc74fcba06ce43ee325510dc6137bd050f96c68Guy Benyei/// \param PreserveHorizontal Don't squash consecutive horizontal whitespace
6344cc74fcba06ce43ee325510dc6137bd050f96c68Guy Benyei/// characters to a single space.
6354cc74fcba06ce43ee325510dc6137bd050f96c68Guy Benyeistatic MemoryBuffer *CanonicalizeInputFile(MemoryBuffer *MB,
6364cc74fcba06ce43ee325510dc6137bd050f96c68Guy Benyei                                           bool PreserveHorizontal) {
6374c842dda3939c6b9f83ba7e8e19e43445cd9a832Chris Lattner  SmallString<128> NewFile;
638adea46ed617982ea07fc3266d52717496c0076ceChris Lattner  NewFile.reserve(MB->getBufferSize());
6397112c86fc208145334aaa04812c794ce6feef416Mikhail Glushenkov
640adea46ed617982ea07fc3266d52717496c0076ceChris Lattner  for (const char *Ptr = MB->getBufferStart(), *End = MB->getBufferEnd();
641adea46ed617982ea07fc3266d52717496c0076ceChris Lattner       Ptr != End; ++Ptr) {
6429f6e03fa1e05f7c59379e68d7626400ca508cfb0NAKAMURA Takumi    // Eliminate trailing dosish \r.
6439f6e03fa1e05f7c59379e68d7626400ca508cfb0NAKAMURA Takumi    if (Ptr <= End - 2 && Ptr[0] == '\r' && Ptr[1] == '\n') {
6449f6e03fa1e05f7c59379e68d7626400ca508cfb0NAKAMURA Takumi      continue;
6459f6e03fa1e05f7c59379e68d7626400ca508cfb0NAKAMURA Takumi    }
6469f6e03fa1e05f7c59379e68d7626400ca508cfb0NAKAMURA Takumi
647c16f8c5e564fc2d69c75e85bdda66ad001d6b99eMichael Liao    // If current char is not a horizontal whitespace or if horizontal
6484cc74fcba06ce43ee325510dc6137bd050f96c68Guy Benyei    // whitespace canonicalization is disabled, dump it to output as is.
6494cc74fcba06ce43ee325510dc6137bd050f96c68Guy Benyei    if (PreserveHorizontal || (*Ptr != ' ' && *Ptr != '\t')) {
650adea46ed617982ea07fc3266d52717496c0076ceChris Lattner      NewFile.push_back(*Ptr);
651adea46ed617982ea07fc3266d52717496c0076ceChris Lattner      continue;
652adea46ed617982ea07fc3266d52717496c0076ceChris Lattner    }
6537112c86fc208145334aaa04812c794ce6feef416Mikhail Glushenkov
654adea46ed617982ea07fc3266d52717496c0076ceChris Lattner    // Otherwise, add one space and advance over neighboring space.
655adea46ed617982ea07fc3266d52717496c0076ceChris Lattner    NewFile.push_back(' ');
656adea46ed617982ea07fc3266d52717496c0076ceChris Lattner    while (Ptr+1 != End &&
657adea46ed617982ea07fc3266d52717496c0076ceChris Lattner           (Ptr[1] == ' ' || Ptr[1] == '\t'))
658adea46ed617982ea07fc3266d52717496c0076ceChris Lattner      ++Ptr;
659adea46ed617982ea07fc3266d52717496c0076ceChris Lattner  }
6607112c86fc208145334aaa04812c794ce6feef416Mikhail Glushenkov
661adea46ed617982ea07fc3266d52717496c0076ceChris Lattner  // Free the old buffer and return a new one.
662adea46ed617982ea07fc3266d52717496c0076ceChris Lattner  MemoryBuffer *MB2 =
6634c842dda3939c6b9f83ba7e8e19e43445cd9a832Chris Lattner    MemoryBuffer::getMemBufferCopy(NewFile.str(), MB->getBufferIdentifier());
6647112c86fc208145334aaa04812c794ce6feef416Mikhail Glushenkov
665adea46ed617982ea07fc3266d52717496c0076ceChris Lattner  delete MB;
666adea46ed617982ea07fc3266d52717496c0076ceChris Lattner  return MB2;
667adea46ed617982ea07fc3266d52717496c0076ceChris Lattner}
668adea46ed617982ea07fc3266d52717496c0076ceChris Lattner
66981cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner
67081cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner/// ReadCheckFile - Read the check file, which specifies the sequence of
67181cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner/// expected strings.  The strings are added to the CheckStrings vector.
6721e5cbcb10adaca5c80121293b6c414d9285ebceeEli Bendersky/// Returns true in case of an error, false otherwise.
67381cb8caa3eb482d45e0fd54f8022384256619178Chris Lattnerstatic bool ReadCheckFile(SourceMgr &SM,
674207e1bcf897d1c732f717b9773029651ecc59ab2Chris Lattner                          std::vector<CheckString> &CheckStrings) {
6753ff9563c3e391954b2e224afcf8b2b0fcc3888aaMichael J. Spencer  OwningPtr<MemoryBuffer> File;
6763ff9563c3e391954b2e224afcf8b2b0fcc3888aaMichael J. Spencer  if (error_code ec =
677dd5af27a74a01f0d03356cea15d3a403f4964f8bRafael Espindola        MemoryBuffer::getFileOrSTDIN(CheckFilename, File)) {
6787112c86fc208145334aaa04812c794ce6feef416Mikhail Glushenkov    errs() << "Could not open check file '" << CheckFilename << "': "
679333fb04506233255f10d8095c9e2de5e5f0fdc6fMichael J. Spencer           << ec.message() << '\n';
68081cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner    return true;
68181cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner  }
6827112c86fc208145334aaa04812c794ce6feef416Mikhail Glushenkov
683adea46ed617982ea07fc3266d52717496c0076ceChris Lattner  // If we want to canonicalize whitespace, strip excess whitespace from the
6844cc74fcba06ce43ee325510dc6137bd050f96c68Guy Benyei  // buffer containing the CHECK lines. Remove DOS style line endings.
6857cdba152bbe4debfb58ed6d9559ef77aae8a0b31Benjamin Kramer  MemoryBuffer *F =
6867cdba152bbe4debfb58ed6d9559ef77aae8a0b31Benjamin Kramer    CanonicalizeInputFile(File.take(), NoCanonicalizeWhiteSpace);
6877112c86fc208145334aaa04812c794ce6feef416Mikhail Glushenkov
68881cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner  SM.AddNewSourceBuffer(F, SMLoc());
68981cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner
690d7e250527c38297c900db43a9e2f1e56b235b3ccChris Lattner  // Find all instances of CheckPrefix followed by : in the file.
69196077036f06478d96c123283a50cfba49858fd40Chris Lattner  StringRef Buffer = F->getBuffer();
69295ab32667456b13ad56634cc7554cde8a50db95aMichael Liao  std::vector<Pattern> DagNotMatches;
6937112c86fc208145334aaa04812c794ce6feef416Mikhail Glushenkov
6941e5cbcb10adaca5c80121293b6c414d9285ebceeEli Bendersky  // LineNumber keeps track of the line on which CheckPrefix instances are
6951e5cbcb10adaca5c80121293b6c414d9285ebceeEli Bendersky  // found.
69670a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko  unsigned LineNumber = 1;
69770a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko
69881cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner  while (1) {
69981cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner    // See if Prefix occurs in the memory buffer.
70070a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko    size_t PrefixLoc = Buffer.find(CheckPrefix);
70181cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner    // If we didn't find a match, we're done.
70270a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko    if (PrefixLoc == StringRef::npos)
70381cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner      break;
7047112c86fc208145334aaa04812c794ce6feef416Mikhail Glushenkov
70570a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko    LineNumber += Buffer.substr(0, PrefixLoc).count('\n');
70670a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko
70770a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko    Buffer = Buffer.substr(PrefixLoc);
70870a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko
70996077036f06478d96c123283a50cfba49858fd40Chris Lattner    const char *CheckPrefixStart = Buffer.data();
7107112c86fc208145334aaa04812c794ce6feef416Mikhail Glushenkov
7115dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner    // When we find a check prefix, keep track of whether we find CHECK: or
7125dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner    // CHECK-NEXT:
713178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin    bool IsCheckNext = false, IsCheckNot = false, IsCheckDag = false,
714178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin         IsCheckLabel = false;
7157112c86fc208145334aaa04812c794ce6feef416Mikhail Glushenkov
716d7e250527c38297c900db43a9e2f1e56b235b3ccChris Lattner    // Verify that the : is present after the prefix.
71796077036f06478d96c123283a50cfba49858fd40Chris Lattner    if (Buffer[CheckPrefix.size()] == ':') {
71896077036f06478d96c123283a50cfba49858fd40Chris Lattner      Buffer = Buffer.substr(CheckPrefix.size()+1);
71996077036f06478d96c123283a50cfba49858fd40Chris Lattner    } else if (Buffer.size() > CheckPrefix.size()+6 &&
72096077036f06478d96c123283a50cfba49858fd40Chris Lattner               memcmp(Buffer.data()+CheckPrefix.size(), "-NEXT:", 6) == 0) {
72130ce40e3f77d1432903c24caf816c54bb260d833Benjamin Kramer      Buffer = Buffer.substr(CheckPrefix.size()+6);
7225dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner      IsCheckNext = true;
723f15380ba8ae35941dcd56d9a288ad023295dde30Chris Lattner    } else if (Buffer.size() > CheckPrefix.size()+5 &&
724f15380ba8ae35941dcd56d9a288ad023295dde30Chris Lattner               memcmp(Buffer.data()+CheckPrefix.size(), "-NOT:", 5) == 0) {
72530ce40e3f77d1432903c24caf816c54bb260d833Benjamin Kramer      Buffer = Buffer.substr(CheckPrefix.size()+5);
726f15380ba8ae35941dcd56d9a288ad023295dde30Chris Lattner      IsCheckNot = true;
72795ab32667456b13ad56634cc7554cde8a50db95aMichael Liao    } else if (Buffer.size() > CheckPrefix.size()+5 &&
72895ab32667456b13ad56634cc7554cde8a50db95aMichael Liao               memcmp(Buffer.data()+CheckPrefix.size(), "-DAG:", 5) == 0) {
72995ab32667456b13ad56634cc7554cde8a50db95aMichael Liao      Buffer = Buffer.substr(CheckPrefix.size()+5);
73095ab32667456b13ad56634cc7554cde8a50db95aMichael Liao      IsCheckDag = true;
731178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin    } else if (Buffer.size() > CheckPrefix.size()+7 &&
732178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin               memcmp(Buffer.data()+CheckPrefix.size(), "-LABEL:", 7) == 0) {
733178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin      Buffer = Buffer.substr(CheckPrefix.size()+7);
734178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin      IsCheckLabel = true;
7355dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner    } else {
73696077036f06478d96c123283a50cfba49858fd40Chris Lattner      Buffer = Buffer.substr(1);
737d7e250527c38297c900db43a9e2f1e56b235b3ccChris Lattner      continue;
738d7e250527c38297c900db43a9e2f1e56b235b3ccChris Lattner    }
7397112c86fc208145334aaa04812c794ce6feef416Mikhail Glushenkov
74081cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner    // Okay, we found the prefix, yay.  Remember the rest of the line, but
74181cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner    // ignore leading and trailing whitespace.
742f15380ba8ae35941dcd56d9a288ad023295dde30Chris Lattner    Buffer = Buffer.substr(Buffer.find_first_not_of(" \t"));
7437112c86fc208145334aaa04812c794ce6feef416Mikhail Glushenkov
74481cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner    // Scan ahead to the end of line.
74596077036f06478d96c123283a50cfba49858fd40Chris Lattner    size_t EOL = Buffer.find_first_of("\n\r");
746a29703e8426763fa5232f9a91e6a5fce4d4244d6Chris Lattner
747e546343799d1b7914024b62f6c188f5c0d66f7b3Dan Gohman    // Remember the location of the start of the pattern, for diagnostics.
748e546343799d1b7914024b62f6c188f5c0d66f7b3Dan Gohman    SMLoc PatternLoc = SMLoc::getFromPointer(Buffer.data());
749e546343799d1b7914024b62f6c188f5c0d66f7b3Dan Gohman
750a29703e8426763fa5232f9a91e6a5fce4d4244d6Chris Lattner    // Parse the pattern.
751a29703e8426763fa5232f9a91e6a5fce4d4244d6Chris Lattner    Pattern P;
75270a870add82dab944b98ee1840fafff33795fc95Alexander Kornienko    if (P.ParsePattern(Buffer.substr(0, EOL), SM, LineNumber))
75381cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner      return true;
7547112c86fc208145334aaa04812c794ce6feef416Mikhail Glushenkov
755178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin    // Verify that CHECK-LABEL lines do not define or use variables
756178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin    if (IsCheckLabel && P.hasVariable()) {
757178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin      SM.PrintMessage(SMLoc::getFromPointer(CheckPrefixStart),
758178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin                      SourceMgr::DK_Error,
759178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin                      "found '"+CheckPrefix+"-LABEL:' with variable definition"
760178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin                      " or use'");
761178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin      return true;
762178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin    }
763178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin
76495ab32667456b13ad56634cc7554cde8a50db95aMichael Liao    P.setMatchNot(IsCheckNot);
76595ab32667456b13ad56634cc7554cde8a50db95aMichael Liao    P.setMatchDag(IsCheckDag);
76695ab32667456b13ad56634cc7554cde8a50db95aMichael Liao
767a29703e8426763fa5232f9a91e6a5fce4d4244d6Chris Lattner    Buffer = Buffer.substr(EOL);
768a29703e8426763fa5232f9a91e6a5fce4d4244d6Chris Lattner
7695dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner    // Verify that CHECK-NEXT lines have at least one CHECK line before them.
7705dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner    if (IsCheckNext && CheckStrings.empty()) {
7715dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner      SM.PrintMessage(SMLoc::getFromPointer(CheckPrefixStart),
7723f2d5f60b31fd057c10f77b2e607b23a8c94f6d3Chris Lattner                      SourceMgr::DK_Error,
7735dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner                      "found '"+CheckPrefix+"-NEXT:' without previous '"+
7743f2d5f60b31fd057c10f77b2e607b23a8c94f6d3Chris Lattner                      CheckPrefix+ ": line");
7755dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner      return true;
7765dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner    }
7777112c86fc208145334aaa04812c794ce6feef416Mikhail Glushenkov
77895ab32667456b13ad56634cc7554cde8a50db95aMichael Liao    // Handle CHECK-DAG/-NOT.
77995ab32667456b13ad56634cc7554cde8a50db95aMichael Liao    if (IsCheckDag || IsCheckNot) {
78095ab32667456b13ad56634cc7554cde8a50db95aMichael Liao      DagNotMatches.push_back(P);
781a29703e8426763fa5232f9a91e6a5fce4d4244d6Chris Lattner      continue;
782a29703e8426763fa5232f9a91e6a5fce4d4244d6Chris Lattner    }
7837112c86fc208145334aaa04812c794ce6feef416Mikhail Glushenkov
78481cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner    // Okay, add the string we captured to the output vector and move on.
7859fc6678bea11f32acba4e9b6624ae9a0d3a9287bChris Lattner    CheckStrings.push_back(CheckString(P,
786e546343799d1b7914024b62f6c188f5c0d66f7b3Dan Gohman                                       PatternLoc,
787178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin                                       IsCheckNext,
788178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin                                       IsCheckLabel));
78995ab32667456b13ad56634cc7554cde8a50db95aMichael Liao    std::swap(DagNotMatches, CheckStrings.back().DagNotStrings);
79081cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner  }
7917112c86fc208145334aaa04812c794ce6feef416Mikhail Glushenkov
79295ab32667456b13ad56634cc7554cde8a50db95aMichael Liao  // Add an EOF pattern for any trailing CHECK-DAG/-NOTs.
79395ab32667456b13ad56634cc7554cde8a50db95aMichael Liao  if (!DagNotMatches.empty()) {
794824c10ece26fd031591b1770acc8a6c2575a3ab8Jakob Stoklund Olesen    CheckStrings.push_back(CheckString(Pattern(true),
795824c10ece26fd031591b1770acc8a6c2575a3ab8Jakob Stoklund Olesen                                       SMLoc::getFromPointer(Buffer.data()),
796178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin                                       false,
797824c10ece26fd031591b1770acc8a6c2575a3ab8Jakob Stoklund Olesen                                       false));
79895ab32667456b13ad56634cc7554cde8a50db95aMichael Liao    std::swap(DagNotMatches, CheckStrings.back().DagNotStrings);
799824c10ece26fd031591b1770acc8a6c2575a3ab8Jakob Stoklund Olesen  }
800824c10ece26fd031591b1770acc8a6c2575a3ab8Jakob Stoklund Olesen
80181cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner  if (CheckStrings.empty()) {
802d7e250527c38297c900db43a9e2f1e56b235b3ccChris Lattner    errs() << "error: no check strings found with prefix '" << CheckPrefix
803d7e250527c38297c900db43a9e2f1e56b235b3ccChris Lattner           << ":'\n";
80481cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner    return true;
80581cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner  }
8067112c86fc208145334aaa04812c794ce6feef416Mikhail Glushenkov
80781cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner  return false;
80881cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner}
80981cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner
81095ab32667456b13ad56634cc7554cde8a50db95aMichael Liaostatic void PrintCheckFailed(const SourceMgr &SM, const SMLoc &Loc,
81195ab32667456b13ad56634cc7554cde8a50db95aMichael Liao                             const Pattern &Pat, StringRef Buffer,
812fafe93c8bcbc538573bc5e890f24f9869a11f846Daniel Dunbar                             StringMap<StringRef> &VariableTable) {
8135dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner  // Otherwise, we have an error, emit an error message.
81495ab32667456b13ad56634cc7554cde8a50db95aMichael Liao  SM.PrintMessage(Loc, SourceMgr::DK_Error,
8153f2d5f60b31fd057c10f77b2e607b23a8c94f6d3Chris Lattner                  "expected string not found in input");
8167112c86fc208145334aaa04812c794ce6feef416Mikhail Glushenkov
8175dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner  // Print the "scanning from here" line.  If the current position is at the
8185dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner  // end of a line, advance to the start of the next line.
81996077036f06478d96c123283a50cfba49858fd40Chris Lattner  Buffer = Buffer.substr(Buffer.find_first_not_of(" \t\n\r"));
8207112c86fc208145334aaa04812c794ce6feef416Mikhail Glushenkov
8213f2d5f60b31fd057c10f77b2e607b23a8c94f6d3Chris Lattner  SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note,
8223f2d5f60b31fd057c10f77b2e607b23a8c94f6d3Chris Lattner                  "scanning from here");
823fafe93c8bcbc538573bc5e890f24f9869a11f846Daniel Dunbar
824fafe93c8bcbc538573bc5e890f24f9869a11f846Daniel Dunbar  // Allow the pattern to print additional information if desired.
82595ab32667456b13ad56634cc7554cde8a50db95aMichael Liao  Pat.PrintFailureInfo(SM, Buffer, VariableTable);
82695ab32667456b13ad56634cc7554cde8a50db95aMichael Liao}
82795ab32667456b13ad56634cc7554cde8a50db95aMichael Liao
82895ab32667456b13ad56634cc7554cde8a50db95aMichael Liaostatic void PrintCheckFailed(const SourceMgr &SM, const CheckString &CheckStr,
82995ab32667456b13ad56634cc7554cde8a50db95aMichael Liao                             StringRef Buffer,
83095ab32667456b13ad56634cc7554cde8a50db95aMichael Liao                             StringMap<StringRef> &VariableTable) {
83195ab32667456b13ad56634cc7554cde8a50db95aMichael Liao  PrintCheckFailed(SM, CheckStr.Loc, CheckStr.Pat, Buffer, VariableTable);
8325dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner}
8335dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner
8343711b7adccc766fdbafbc6b22c2bb6c45181a3b9Chris Lattner/// CountNumNewlinesBetween - Count the number of newlines in the specified
8353711b7adccc766fdbafbc6b22c2bb6c45181a3b9Chris Lattner/// range.
8363711b7adccc766fdbafbc6b22c2bb6c45181a3b9Chris Lattnerstatic unsigned CountNumNewlinesBetween(StringRef Range) {
8375dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner  unsigned NumNewLines = 0;
8383711b7adccc766fdbafbc6b22c2bb6c45181a3b9Chris Lattner  while (1) {
8395dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner    // Scan for newline.
8403711b7adccc766fdbafbc6b22c2bb6c45181a3b9Chris Lattner    Range = Range.substr(Range.find_first_of("\n\r"));
8413711b7adccc766fdbafbc6b22c2bb6c45181a3b9Chris Lattner    if (Range.empty()) return NumNewLines;
8427112c86fc208145334aaa04812c794ce6feef416Mikhail Glushenkov
8435dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner    ++NumNewLines;
8447112c86fc208145334aaa04812c794ce6feef416Mikhail Glushenkov
8455dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner    // Handle \n\r and \r\n as a single newline.
8463711b7adccc766fdbafbc6b22c2bb6c45181a3b9Chris Lattner    if (Range.size() > 1 &&
8473711b7adccc766fdbafbc6b22c2bb6c45181a3b9Chris Lattner        (Range[1] == '\n' || Range[1] == '\r') &&
8483711b7adccc766fdbafbc6b22c2bb6c45181a3b9Chris Lattner        (Range[0] != Range[1]))
8493711b7adccc766fdbafbc6b22c2bb6c45181a3b9Chris Lattner      Range = Range.substr(1);
8503711b7adccc766fdbafbc6b22c2bb6c45181a3b9Chris Lattner    Range = Range.substr(1);
8515dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner  }
8525dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner}
8535dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner
8547efbbd61eb0aa85ec189db8f02c85ad9078946e9Michael Liaosize_t CheckString::Check(const SourceMgr &SM, StringRef Buffer,
855178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin                          bool IsLabel, size_t &MatchLen,
8567efbbd61eb0aa85ec189db8f02c85ad9078946e9Michael Liao                          StringMap<StringRef> &VariableTable) const {
85795ab32667456b13ad56634cc7554cde8a50db95aMichael Liao  size_t LastPos = 0;
85895ab32667456b13ad56634cc7554cde8a50db95aMichael Liao  std::vector<const Pattern *> NotStrings;
85995ab32667456b13ad56634cc7554cde8a50db95aMichael Liao
860178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin  if (!IsLabel) {
861178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin    // Match "dag strings" (with mixed "not strings" if any).
862178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin    LastPos = CheckDag(SM, Buffer, NotStrings, VariableTable);
863178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin    if (LastPos == StringRef::npos)
864178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin      return StringRef::npos;
865178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin  }
86695ab32667456b13ad56634cc7554cde8a50db95aMichael Liao
86795ab32667456b13ad56634cc7554cde8a50db95aMichael Liao  // Match itself from the last position after matching CHECK-DAG.
86895ab32667456b13ad56634cc7554cde8a50db95aMichael Liao  StringRef MatchBuffer = Buffer.substr(LastPos);
86995ab32667456b13ad56634cc7554cde8a50db95aMichael Liao  size_t MatchPos = Pat.Match(MatchBuffer, MatchLen, VariableTable);
8707efbbd61eb0aa85ec189db8f02c85ad9078946e9Michael Liao  if (MatchPos == StringRef::npos) {
87195ab32667456b13ad56634cc7554cde8a50db95aMichael Liao    PrintCheckFailed(SM, *this, MatchBuffer, VariableTable);
8727efbbd61eb0aa85ec189db8f02c85ad9078946e9Michael Liao    return StringRef::npos;
8737efbbd61eb0aa85ec189db8f02c85ad9078946e9Michael Liao  }
87495ab32667456b13ad56634cc7554cde8a50db95aMichael Liao  MatchPos += LastPos;
8757efbbd61eb0aa85ec189db8f02c85ad9078946e9Michael Liao
876178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin  if (!IsLabel) {
877178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin    StringRef SkippedRegion = Buffer.substr(LastPos, MatchPos);
8787efbbd61eb0aa85ec189db8f02c85ad9078946e9Michael Liao
879178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin    // If this check is a "CHECK-NEXT", verify that the previous match was on
880178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin    // the previous line (i.e. that there is one newline between them).
881178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin    if (CheckNext(SM, SkippedRegion))
882178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin      return StringRef::npos;
8837efbbd61eb0aa85ec189db8f02c85ad9078946e9Michael Liao
884178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin    // If this match had "not strings", verify that they don't exist in the
885178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin    // skipped region.
886178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin    if (CheckNot(SM, SkippedRegion, NotStrings, VariableTable))
887178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin      return StringRef::npos;
888178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin  }
8897efbbd61eb0aa85ec189db8f02c85ad9078946e9Michael Liao
8907efbbd61eb0aa85ec189db8f02c85ad9078946e9Michael Liao  return MatchPos;
8917efbbd61eb0aa85ec189db8f02c85ad9078946e9Michael Liao}
8927efbbd61eb0aa85ec189db8f02c85ad9078946e9Michael Liao
8937efbbd61eb0aa85ec189db8f02c85ad9078946e9Michael Liaobool CheckString::CheckNext(const SourceMgr &SM, StringRef Buffer) const {
8947efbbd61eb0aa85ec189db8f02c85ad9078946e9Michael Liao  if (!IsCheckNext)
8957efbbd61eb0aa85ec189db8f02c85ad9078946e9Michael Liao    return false;
8967efbbd61eb0aa85ec189db8f02c85ad9078946e9Michael Liao
8977efbbd61eb0aa85ec189db8f02c85ad9078946e9Michael Liao  // Count the number of newlines between the previous match and this one.
8987efbbd61eb0aa85ec189db8f02c85ad9078946e9Michael Liao  assert(Buffer.data() !=
8997efbbd61eb0aa85ec189db8f02c85ad9078946e9Michael Liao         SM.getMemoryBuffer(
9007efbbd61eb0aa85ec189db8f02c85ad9078946e9Michael Liao           SM.FindBufferContainingLoc(
9017efbbd61eb0aa85ec189db8f02c85ad9078946e9Michael Liao             SMLoc::getFromPointer(Buffer.data())))->getBufferStart() &&
9027efbbd61eb0aa85ec189db8f02c85ad9078946e9Michael Liao         "CHECK-NEXT can't be the first check in a file");
9037efbbd61eb0aa85ec189db8f02c85ad9078946e9Michael Liao
9047efbbd61eb0aa85ec189db8f02c85ad9078946e9Michael Liao  unsigned NumNewLines = CountNumNewlinesBetween(Buffer);
9057efbbd61eb0aa85ec189db8f02c85ad9078946e9Michael Liao
9067efbbd61eb0aa85ec189db8f02c85ad9078946e9Michael Liao  if (NumNewLines == 0) {
9077efbbd61eb0aa85ec189db8f02c85ad9078946e9Michael Liao    SM.PrintMessage(Loc, SourceMgr::DK_Error, CheckPrefix+
9087efbbd61eb0aa85ec189db8f02c85ad9078946e9Michael Liao                    "-NEXT: is on the same line as previous match");
9097efbbd61eb0aa85ec189db8f02c85ad9078946e9Michael Liao    SM.PrintMessage(SMLoc::getFromPointer(Buffer.end()),
9107efbbd61eb0aa85ec189db8f02c85ad9078946e9Michael Liao                    SourceMgr::DK_Note, "'next' match was here");
9117efbbd61eb0aa85ec189db8f02c85ad9078946e9Michael Liao    SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note,
9127efbbd61eb0aa85ec189db8f02c85ad9078946e9Michael Liao                    "previous match ended here");
9137efbbd61eb0aa85ec189db8f02c85ad9078946e9Michael Liao    return true;
9147efbbd61eb0aa85ec189db8f02c85ad9078946e9Michael Liao  }
9157efbbd61eb0aa85ec189db8f02c85ad9078946e9Michael Liao
9167efbbd61eb0aa85ec189db8f02c85ad9078946e9Michael Liao  if (NumNewLines != 1) {
9177efbbd61eb0aa85ec189db8f02c85ad9078946e9Michael Liao    SM.PrintMessage(Loc, SourceMgr::DK_Error, CheckPrefix+
9187efbbd61eb0aa85ec189db8f02c85ad9078946e9Michael Liao                    "-NEXT: is not on the line after the previous match");
9197efbbd61eb0aa85ec189db8f02c85ad9078946e9Michael Liao    SM.PrintMessage(SMLoc::getFromPointer(Buffer.end()),
9207efbbd61eb0aa85ec189db8f02c85ad9078946e9Michael Liao                    SourceMgr::DK_Note, "'next' match was here");
9217efbbd61eb0aa85ec189db8f02c85ad9078946e9Michael Liao    SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note,
9227efbbd61eb0aa85ec189db8f02c85ad9078946e9Michael Liao                    "previous match ended here");
9237efbbd61eb0aa85ec189db8f02c85ad9078946e9Michael Liao    return true;
9247efbbd61eb0aa85ec189db8f02c85ad9078946e9Michael Liao  }
9257efbbd61eb0aa85ec189db8f02c85ad9078946e9Michael Liao
9267efbbd61eb0aa85ec189db8f02c85ad9078946e9Michael Liao  return false;
9277efbbd61eb0aa85ec189db8f02c85ad9078946e9Michael Liao}
9287efbbd61eb0aa85ec189db8f02c85ad9078946e9Michael Liao
9297efbbd61eb0aa85ec189db8f02c85ad9078946e9Michael Liaobool CheckString::CheckNot(const SourceMgr &SM, StringRef Buffer,
93095ab32667456b13ad56634cc7554cde8a50db95aMichael Liao                           const std::vector<const Pattern *> &NotStrings,
9317efbbd61eb0aa85ec189db8f02c85ad9078946e9Michael Liao                           StringMap<StringRef> &VariableTable) const {
9327efbbd61eb0aa85ec189db8f02c85ad9078946e9Michael Liao  for (unsigned ChunkNo = 0, e = NotStrings.size();
9337efbbd61eb0aa85ec189db8f02c85ad9078946e9Michael Liao       ChunkNo != e; ++ChunkNo) {
93495ab32667456b13ad56634cc7554cde8a50db95aMichael Liao    const Pattern *Pat = NotStrings[ChunkNo];
93595ab32667456b13ad56634cc7554cde8a50db95aMichael Liao    assert(Pat->getMatchNot() && "Expect CHECK-NOT!");
93695ab32667456b13ad56634cc7554cde8a50db95aMichael Liao
9377efbbd61eb0aa85ec189db8f02c85ad9078946e9Michael Liao    size_t MatchLen = 0;
93895ab32667456b13ad56634cc7554cde8a50db95aMichael Liao    size_t Pos = Pat->Match(Buffer, MatchLen, VariableTable);
9397efbbd61eb0aa85ec189db8f02c85ad9078946e9Michael Liao
9407efbbd61eb0aa85ec189db8f02c85ad9078946e9Michael Liao    if (Pos == StringRef::npos) continue;
9417efbbd61eb0aa85ec189db8f02c85ad9078946e9Michael Liao
9427efbbd61eb0aa85ec189db8f02c85ad9078946e9Michael Liao    SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()+Pos),
9437efbbd61eb0aa85ec189db8f02c85ad9078946e9Michael Liao                    SourceMgr::DK_Error,
9447efbbd61eb0aa85ec189db8f02c85ad9078946e9Michael Liao                    CheckPrefix+"-NOT: string occurred!");
94595ab32667456b13ad56634cc7554cde8a50db95aMichael Liao    SM.PrintMessage(Pat->getLoc(), SourceMgr::DK_Note,
9467efbbd61eb0aa85ec189db8f02c85ad9078946e9Michael Liao                    CheckPrefix+"-NOT: pattern specified here");
9477efbbd61eb0aa85ec189db8f02c85ad9078946e9Michael Liao    return true;
9487efbbd61eb0aa85ec189db8f02c85ad9078946e9Michael Liao  }
9497efbbd61eb0aa85ec189db8f02c85ad9078946e9Michael Liao
9507efbbd61eb0aa85ec189db8f02c85ad9078946e9Michael Liao  return false;
9517efbbd61eb0aa85ec189db8f02c85ad9078946e9Michael Liao}
9527efbbd61eb0aa85ec189db8f02c85ad9078946e9Michael Liao
95395ab32667456b13ad56634cc7554cde8a50db95aMichael Liaosize_t CheckString::CheckDag(const SourceMgr &SM, StringRef Buffer,
95495ab32667456b13ad56634cc7554cde8a50db95aMichael Liao                             std::vector<const Pattern *> &NotStrings,
95595ab32667456b13ad56634cc7554cde8a50db95aMichael Liao                             StringMap<StringRef> &VariableTable) const {
95695ab32667456b13ad56634cc7554cde8a50db95aMichael Liao  if (DagNotStrings.empty())
95795ab32667456b13ad56634cc7554cde8a50db95aMichael Liao    return 0;
95895ab32667456b13ad56634cc7554cde8a50db95aMichael Liao
95995ab32667456b13ad56634cc7554cde8a50db95aMichael Liao  size_t LastPos = 0;
96095ab32667456b13ad56634cc7554cde8a50db95aMichael Liao  size_t StartPos = LastPos;
96195ab32667456b13ad56634cc7554cde8a50db95aMichael Liao
96295ab32667456b13ad56634cc7554cde8a50db95aMichael Liao  for (unsigned ChunkNo = 0, e = DagNotStrings.size();
96395ab32667456b13ad56634cc7554cde8a50db95aMichael Liao       ChunkNo != e; ++ChunkNo) {
96495ab32667456b13ad56634cc7554cde8a50db95aMichael Liao    const Pattern &Pat = DagNotStrings[ChunkNo];
96595ab32667456b13ad56634cc7554cde8a50db95aMichael Liao
96695ab32667456b13ad56634cc7554cde8a50db95aMichael Liao    assert((Pat.getMatchDag() ^ Pat.getMatchNot()) &&
96795ab32667456b13ad56634cc7554cde8a50db95aMichael Liao           "Invalid CHECK-DAG or CHECK-NOT!");
96895ab32667456b13ad56634cc7554cde8a50db95aMichael Liao
96995ab32667456b13ad56634cc7554cde8a50db95aMichael Liao    if (Pat.getMatchNot()) {
97095ab32667456b13ad56634cc7554cde8a50db95aMichael Liao      NotStrings.push_back(&Pat);
97195ab32667456b13ad56634cc7554cde8a50db95aMichael Liao      continue;
97295ab32667456b13ad56634cc7554cde8a50db95aMichael Liao    }
97395ab32667456b13ad56634cc7554cde8a50db95aMichael Liao
97495ab32667456b13ad56634cc7554cde8a50db95aMichael Liao    assert(Pat.getMatchDag() && "Expect CHECK-DAG!");
97595ab32667456b13ad56634cc7554cde8a50db95aMichael Liao
97695ab32667456b13ad56634cc7554cde8a50db95aMichael Liao    size_t MatchLen = 0, MatchPos;
97795ab32667456b13ad56634cc7554cde8a50db95aMichael Liao
97895ab32667456b13ad56634cc7554cde8a50db95aMichael Liao    // CHECK-DAG always matches from the start.
97995ab32667456b13ad56634cc7554cde8a50db95aMichael Liao    StringRef MatchBuffer = Buffer.substr(StartPos);
98095ab32667456b13ad56634cc7554cde8a50db95aMichael Liao    MatchPos = Pat.Match(MatchBuffer, MatchLen, VariableTable);
98195ab32667456b13ad56634cc7554cde8a50db95aMichael Liao    // With a group of CHECK-DAGs, a single mismatching means the match on
98295ab32667456b13ad56634cc7554cde8a50db95aMichael Liao    // that group of CHECK-DAGs fails immediately.
98395ab32667456b13ad56634cc7554cde8a50db95aMichael Liao    if (MatchPos == StringRef::npos) {
98495ab32667456b13ad56634cc7554cde8a50db95aMichael Liao      PrintCheckFailed(SM, Pat.getLoc(), Pat, MatchBuffer, VariableTable);
98595ab32667456b13ad56634cc7554cde8a50db95aMichael Liao      return StringRef::npos;
98695ab32667456b13ad56634cc7554cde8a50db95aMichael Liao    }
98795ab32667456b13ad56634cc7554cde8a50db95aMichael Liao    // Re-calc it as the offset relative to the start of the original string.
98895ab32667456b13ad56634cc7554cde8a50db95aMichael Liao    MatchPos += StartPos;
98995ab32667456b13ad56634cc7554cde8a50db95aMichael Liao
99095ab32667456b13ad56634cc7554cde8a50db95aMichael Liao    if (!NotStrings.empty()) {
99195ab32667456b13ad56634cc7554cde8a50db95aMichael Liao      if (MatchPos < LastPos) {
99295ab32667456b13ad56634cc7554cde8a50db95aMichael Liao        // Reordered?
99395ab32667456b13ad56634cc7554cde8a50db95aMichael Liao        SM.PrintMessage(SMLoc::getFromPointer(Buffer.data() + MatchPos),
99495ab32667456b13ad56634cc7554cde8a50db95aMichael Liao                        SourceMgr::DK_Error,
99595ab32667456b13ad56634cc7554cde8a50db95aMichael Liao                        CheckPrefix+"-DAG: found a match of CHECK-DAG"
99695ab32667456b13ad56634cc7554cde8a50db95aMichael Liao                        " reordering across a CHECK-NOT");
99795ab32667456b13ad56634cc7554cde8a50db95aMichael Liao        SM.PrintMessage(SMLoc::getFromPointer(Buffer.data() + LastPos),
99895ab32667456b13ad56634cc7554cde8a50db95aMichael Liao                        SourceMgr::DK_Note,
99995ab32667456b13ad56634cc7554cde8a50db95aMichael Liao                        CheckPrefix+"-DAG: the farthest match of CHECK-DAG"
100095ab32667456b13ad56634cc7554cde8a50db95aMichael Liao                        " is found here");
100195ab32667456b13ad56634cc7554cde8a50db95aMichael Liao        SM.PrintMessage(NotStrings[0]->getLoc(), SourceMgr::DK_Note,
100295ab32667456b13ad56634cc7554cde8a50db95aMichael Liao                        CheckPrefix+"-NOT: the crossed pattern specified"
100395ab32667456b13ad56634cc7554cde8a50db95aMichael Liao                        " here");
100495ab32667456b13ad56634cc7554cde8a50db95aMichael Liao        SM.PrintMessage(Pat.getLoc(), SourceMgr::DK_Note,
100595ab32667456b13ad56634cc7554cde8a50db95aMichael Liao                        CheckPrefix+"-DAG: the reordered pattern specified"
100695ab32667456b13ad56634cc7554cde8a50db95aMichael Liao                        " here");
100795ab32667456b13ad56634cc7554cde8a50db95aMichael Liao        return StringRef::npos;
100895ab32667456b13ad56634cc7554cde8a50db95aMichael Liao      }
100995ab32667456b13ad56634cc7554cde8a50db95aMichael Liao      // All subsequent CHECK-DAGs should be matched from the farthest
101095ab32667456b13ad56634cc7554cde8a50db95aMichael Liao      // position of all precedent CHECK-DAGs (including this one.)
101195ab32667456b13ad56634cc7554cde8a50db95aMichael Liao      StartPos = LastPos;
101295ab32667456b13ad56634cc7554cde8a50db95aMichael Liao      // If there's CHECK-NOTs between two CHECK-DAGs or from CHECK to
101395ab32667456b13ad56634cc7554cde8a50db95aMichael Liao      // CHECK-DAG, verify that there's no 'not' strings occurred in that
101495ab32667456b13ad56634cc7554cde8a50db95aMichael Liao      // region.
101595ab32667456b13ad56634cc7554cde8a50db95aMichael Liao      StringRef SkippedRegion = Buffer.substr(LastPos, MatchPos);
101695ab32667456b13ad56634cc7554cde8a50db95aMichael Liao      size_t Pos = CheckNot(SM, SkippedRegion, NotStrings, VariableTable);
101795ab32667456b13ad56634cc7554cde8a50db95aMichael Liao      if (Pos != StringRef::npos)
101895ab32667456b13ad56634cc7554cde8a50db95aMichael Liao        return StringRef::npos;
101995ab32667456b13ad56634cc7554cde8a50db95aMichael Liao      // Clear "not strings".
102095ab32667456b13ad56634cc7554cde8a50db95aMichael Liao      NotStrings.clear();
102195ab32667456b13ad56634cc7554cde8a50db95aMichael Liao    }
102295ab32667456b13ad56634cc7554cde8a50db95aMichael Liao
102395ab32667456b13ad56634cc7554cde8a50db95aMichael Liao    // Update the last position with CHECK-DAG matches.
102495ab32667456b13ad56634cc7554cde8a50db95aMichael Liao    LastPos = std::max(MatchPos + MatchLen, LastPos);
102595ab32667456b13ad56634cc7554cde8a50db95aMichael Liao  }
102695ab32667456b13ad56634cc7554cde8a50db95aMichael Liao
102795ab32667456b13ad56634cc7554cde8a50db95aMichael Liao  return LastPos;
102895ab32667456b13ad56634cc7554cde8a50db95aMichael Liao}
102995ab32667456b13ad56634cc7554cde8a50db95aMichael Liao
103081cb8caa3eb482d45e0fd54f8022384256619178Chris Lattnerint main(int argc, char **argv) {
103181cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner  sys::PrintStackTraceOnErrorSignal();
103281cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner  PrettyStackTraceProgram X(argc, argv);
103381cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner  cl::ParseCommandLineOptions(argc, argv);
103481cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner
103581cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner  SourceMgr SM;
10367112c86fc208145334aaa04812c794ce6feef416Mikhail Glushenkov
103781cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner  // Read the expected strings from the check file.
1038207e1bcf897d1c732f717b9773029651ecc59ab2Chris Lattner  std::vector<CheckString> CheckStrings;
103981cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner  if (ReadCheckFile(SM, CheckStrings))
104081cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner    return 2;
104181cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner
104281cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner  // Open the file to check and add it to SourceMgr.
10433ff9563c3e391954b2e224afcf8b2b0fcc3888aaMichael J. Spencer  OwningPtr<MemoryBuffer> File;
10443ff9563c3e391954b2e224afcf8b2b0fcc3888aaMichael J. Spencer  if (error_code ec =
1045dd5af27a74a01f0d03356cea15d3a403f4964f8bRafael Espindola        MemoryBuffer::getFileOrSTDIN(InputFilename, File)) {
10467112c86fc208145334aaa04812c794ce6feef416Mikhail Glushenkov    errs() << "Could not open input file '" << InputFilename << "': "
1047333fb04506233255f10d8095c9e2de5e5f0fdc6fMichael J. Spencer           << ec.message() << '\n';
10487f8e76f5140be7cc9ed1cb66cdcdedfa28147641Eli Bendersky    return 2;
104981cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner  }
10507112c86fc208145334aaa04812c794ce6feef416Mikhail Glushenkov
10517cdba152bbe4debfb58ed6d9559ef77aae8a0b31Benjamin Kramer  if (File->getBufferSize() == 0) {
10521aac1864cfb66ae3d322ff7e28738d03bc1d1bfcChris Lattner    errs() << "FileCheck error: '" << InputFilename << "' is empty.\n";
10537f8e76f5140be7cc9ed1cb66cdcdedfa28147641Eli Bendersky    return 2;
10541aac1864cfb66ae3d322ff7e28738d03bc1d1bfcChris Lattner  }
10557cdba152bbe4debfb58ed6d9559ef77aae8a0b31Benjamin Kramer
105688a7e9ee8dd2f1d2f40cdb9c378f050e45161783Chris Lattner  // Remove duplicate spaces in the input file if requested.
10574cc74fcba06ce43ee325510dc6137bd050f96c68Guy Benyei  // Remove DOS style line endings.
10587cdba152bbe4debfb58ed6d9559ef77aae8a0b31Benjamin Kramer  MemoryBuffer *F =
10597cdba152bbe4debfb58ed6d9559ef77aae8a0b31Benjamin Kramer    CanonicalizeInputFile(File.take(), NoCanonicalizeWhiteSpace);
10607112c86fc208145334aaa04812c794ce6feef416Mikhail Glushenkov
106181cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner  SM.AddNewSourceBuffer(F, SMLoc());
10627112c86fc208145334aaa04812c794ce6feef416Mikhail Glushenkov
1063eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner  /// VariableTable - This holds all the current filecheck variables.
1064eec96958cd53ebb61bebfd3af416ace380df6f6cChris Lattner  StringMap<StringRef> VariableTable;
10657112c86fc208145334aaa04812c794ce6feef416Mikhail Glushenkov
106681cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner  // Check that we have all of the expected strings, in order, in the input
106781cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner  // file.
106896077036f06478d96c123283a50cfba49858fd40Chris Lattner  StringRef Buffer = F->getBuffer();
10697112c86fc208145334aaa04812c794ce6feef416Mikhail Glushenkov
1070178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin  bool hasError = false;
10717112c86fc208145334aaa04812c794ce6feef416Mikhail Glushenkov
1072178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin  unsigned i = 0, j = 0, e = CheckStrings.size();
1073178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin
1074178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin  while (true) {
1075178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin    StringRef CheckRegion;
1076178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin    if (j == e) {
1077178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin      CheckRegion = Buffer;
1078178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin    } else {
1079178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin      const CheckString &CheckLabelStr = CheckStrings[j];
1080178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin      if (!CheckLabelStr.IsCheckLabel) {
1081178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin        ++j;
1082178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin        continue;
1083178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin      }
1084178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin
1085178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin      // Scan to next CHECK-LABEL match, ignoring CHECK-NOT and CHECK-DAG
1086178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin      size_t MatchLabelLen = 0;
1087178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin      size_t MatchLabelPos = CheckLabelStr.Check(SM, Buffer, true,
1088178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin                                                 MatchLabelLen, VariableTable);
1089178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin      if (MatchLabelPos == StringRef::npos) {
1090178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin        hasError = true;
1091178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin        break;
1092178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin      }
10937112c86fc208145334aaa04812c794ce6feef416Mikhail Glushenkov
1094178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin      CheckRegion = Buffer.substr(0, MatchLabelPos + MatchLabelLen);
1095178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin      Buffer = Buffer.substr(MatchLabelPos + MatchLabelLen);
1096178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin      ++j;
1097178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin    }
10985dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner
1099178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin    for ( ; i != j; ++i) {
1100178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin      const CheckString &CheckStr = CheckStrings[i];
1101178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin
1102178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin      // Check each string within the scanned region, including a second check
1103178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin      // of any final CHECK-LABEL (to verify CHECK-NOT and CHECK-DAG)
1104178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin      size_t MatchLen = 0;
1105178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin      size_t MatchPos = CheckStr.Check(SM, CheckRegion, false, MatchLen,
1106178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin                                       VariableTable);
1107178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin
1108178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin      if (MatchPos == StringRef::npos) {
1109178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin        hasError = true;
1110178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin        i = j;
1111178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin        break;
1112178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin      }
1113178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin
1114178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin      CheckRegion = CheckRegion.substr(MatchPos + MatchLen);
1115178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin    }
1116178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin
1117178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin    if (j == e)
1118178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin      break;
111981cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner  }
11207112c86fc208145334aaa04812c794ce6feef416Mikhail Glushenkov
1121178504b07b793b3fde46d950b8f10e0794193e02Stephen Lin  return hasError ? 1 : 0;
112281cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner}
1123