Index: docs/CommandGuide/FileCheck.rst =================================================================== --- docs/CommandGuide/FileCheck.rst +++ docs/CommandGuide/FileCheck.rst @@ -81,6 +81,10 @@ Show the version number of this program. +.. option:: --regex-prefixes + + Enable option of using regular expressions as prefix in check strings. + EXIT STATUS ----------- @@ -169,6 +173,56 @@ In this case, we're testing that we get the expected code generation with both 32-bit and 64-bit code generation. +The FileCheck -regex-prefixes option +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The FileCheck :option:`-regex-prefixes` option allows use regular expressions +as prefixes for check strings. If you use different prefixes, checks for some +prefixes can be repeated, then if names of these prefixes will match same +regular expression, you can use regular expression without prefix. +For example: + +.. code-block:: llvm + + //{{ARC[0-9]*}}: + +It’s equal to + +.. code-block:: llvm + + //ARC: + //ARC1: + //ARC23: + +and etc. + +Wildcard for prefixes +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +In FileCheck you can set your own prefixes for checking. If you use different +prefixes, but there are some checks, which should match with all prefixes, you +can used wildcard prefix {{*}}. + +For example + +.. code-block:: llvm + + //{{*}}-SAME: {{[a-z]+}} + +It’s equal to + +.. code-block:: llvm + + // A-WORD: {{[a-z]+}} + // B-WORD: {{[a-z]+}} + +and etc + +It will find match for this regex if you run FileCheck with any prefix. + +It’s necessary to use :option:`-regex-prefixes` option if you would like to have +this feature enable. + The "CHECK-NEXT:" directive ~~~~~~~~~~~~~~~~~~~~~~~~~~~ Index: test/FileCheck/check-regexp-prefix.txt =================================================================== --- /dev/null +++ test/FileCheck/check-regexp-prefix.txt @@ -0,0 +1,16 @@ +// RUN: FileCheck -check-prefix=A -regex-prefixes -input-file %s %s +// RUN: FileCheck -check-prefix=b -regex-prefixes -input-file %s %s + +for B check +first +next-line + +// {{[A-Z]+}}: first +// {{[a-z0-9]+}}: for {{B}} + + +// {{[A-C0-9]+}}-NEXT: {{next-line}} + +same for both +// {{[A-Za-z0-9]+}}: same +// {{[A-Za-z0-9]+}}-SAME: both Index: test/FileCheck/check-wildcard-prefix.txt =================================================================== --- /dev/null +++ test/FileCheck/check-wildcard-prefix.txt @@ -0,0 +1,13 @@ +// RUN: FileCheck -check-prefix=A -regex-prefixes -input-file %s %s +// RUN: not FileCheck -check-prefix=B -regex-prefixes -input-file %s %s + +for B check +first +next-line +// A: first +// B: for B +// {{*}}-NEXT: {{next-line}} + +same for both +// {{*}}: same +// {{*}}-SAME: both \ No newline at end of file Index: utils/FileCheck/FileCheck.cpp =================================================================== --- utils/FileCheck/FileCheck.cpp +++ utils/FileCheck/FileCheck.cpp @@ -73,6 +73,10 @@ "Allows leading and trailing whitespace if --strict-whitespace\n" "is not also passed.")); +static cl::opt +RegexPrefixesOn ("regex-prefixes", + cl::desc("Use checks with prefixes which can be described as regular expressions.")); + typedef cl::list::const_iterator prefix_iterator; //===----------------------------------------------------------------------===// @@ -792,6 +796,41 @@ for (StringRef Prefix : CheckPrefixes) { size_t PrefixLoc = Buffer.find(Prefix); + if (RegexPrefixesOn) { + SmallVector Matches; + // Try ti find prefixes defined as regexes. + Regex PrefixesWithRegexes(StringRef("\\{\\{(.+)\\}\\}(-.+)?:.+$")); + StringRef BufferCopy = Buffer; + size_t DiffInLoc = 0; + + while (PrefixesWithRegexes.match(BufferCopy, &Matches) && + (DiffInLoc < PrefixLoc || PrefixLoc == StringRef::npos)) { + // Get regex part + StringRef RegexPart = Matches[1]; + if (RegexPart.find("}}") != StringRef::npos) { + RegexPart = RegexPart.substr(0, RegexPart.find("}}")); + } + + size_t RegexPrefixLoc = Matches[1].data() - BufferCopy.data(); + DiffInLoc += RegexPrefixLoc; + // Check if current prefix matches with found. + if (Regex(RegexPart).match(Prefix)) { + if (DiffInLoc < PrefixLoc) { + PrefixLoc = DiffInLoc; + Prefix = StringRef(RegexPart.str() + "}}"); + } + } + + if (BufferCopy.find("\n", RegexPrefixLoc) != StringRef::npos) { + DiffInLoc += BufferCopy.find("\n", RegexPrefixLoc) - RegexPrefixLoc; + BufferCopy = + BufferCopy.drop_front(BufferCopy.find("\n", RegexPrefixLoc)); + } else { + BufferCopy = BufferCopy.drop_front(RegexPrefixLoc); + } + } + } + if (PrefixLoc == StringRef::npos) continue; @@ -1301,6 +1340,11 @@ static void AddCheckPrefixIfNeeded() { if (CheckPrefixes.empty()) CheckPrefixes.push_back("CHECK"); + // Prefix wild-card which will be always matched. + if (RegexPrefixesOn) + if (std::find(CheckPrefixes.begin(), CheckPrefixes.end(), "{{*}}") == + CheckPrefixes.end()) + CheckPrefixes.push_back("{{*}}"); } static void DumpCommandLine(int argc, char **argv) {