Index: docs/CommandGuide/FileCheck.rst =================================================================== --- docs/CommandGuide/FileCheck.rst +++ docs/CommandGuide/FileCheck.rst @@ -77,6 +77,11 @@ -verify``. With this option FileCheck will verify that input does not contain warnings not covered by any ``CHECK:`` patterns. +.. option:: --match-new-line-characters + + When this option is specified, the string ``\n`` in regular expression + patterns matches newline characters. + .. option:: -version Show the version number of this program. @@ -460,23 +465,3 @@ // CHECK-NEXT: {{^ \^}} // CHECK-NEXT: {{^ ;}} int a - -Matching Newline Characters -~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -To match newline characters in regular expressions the character class -``[[:space:]]`` can be used. For example, the following pattern: - -.. code-block:: c++ - - // CHECK: DW_AT_location [DW_FORM_sec_offset] ([[DLOC:0x[0-9a-f]+]]){{[[:space:]].*}}"intd" - -matches output of the form (from llvm-dwarfdump): - -.. code-block:: text - - DW_AT_location [DW_FORM_sec_offset] (0x00000233) - DW_AT_name [DW_FORM_strp] ( .debug_str[0x000000c9] = "intd") - -letting us set the :program:`FileCheck` variable ``DLOC`` to the desired value -``0x00000233``, extracted from the line immediately preceding "``intd``". Index: test/FileCheck/explicit-newlines.txt =================================================================== --- test/FileCheck/explicit-newlines.txt +++ test/FileCheck/explicit-newlines.txt @@ -0,0 +1,20 @@ +; Test that a literal new line only matches if switch is specified +; RUN: not FileCheck %s -input-file=%s -check-prefix=NEWLINE +; RUN: FileCheck %s -input-file=%s -check-prefix=NEWLINE -match-new-line-characters +; NEWLINE: a{{\n}}newline +a +newline + +; Test that backslash escape behaviour functions correctly before 'n' +; RUN: FileCheck %s -input-file=%s -check-prefix=BACKSLASHES +; RUN: FileCheck %s -input-file=%s -check-prefix=BACKSLASHES -match-new-line-characters +; BACKSLASHES: {{^\\n}} +; BACKSLASHES: {{^\\\\n}} +\n +\\n + +; RUN: not FileCheck %s -input-file=%s -check-prefix=ODDSLASH +; RUN: FileCheck %s -input-file=%s -check-prefix=ODDSLASH -match-new-line-characters +; ODDSLASH: the{{\\\n}}next line +the\ +next line Index: utils/FileCheck/FileCheck.cpp =================================================================== --- utils/FileCheck/FileCheck.cpp +++ utils/FileCheck/FileCheck.cpp @@ -73,6 +73,11 @@ "Allows leading and trailing whitespace if --strict-whitespace\n" "is not also passed.")); +static cl::opt + MatchNewLineChars("match-new-line-characters", cl::init(false), + cl::desc("Treats \"\\n\" in regular expression patterns " + "as a literal newline character.")); + typedef cl::list::const_iterator prefix_iterator; //===----------------------------------------------------------------------===// @@ -155,6 +160,34 @@ size_t FindRegexVarEnd(StringRef Str, SourceMgr &SM); }; +/// Converts instances of the substring "\n" into a literal '\n'. \p PatternStr +/// is the string to modify. Returns the modified string. +std::string ParseNewLineCharacters(StringRef PatternStr) { + std::string ParsedStr; + std::size_t Prev = 0; + std::size_t Size = PatternStr.size(); + for (std::size_t Pos = 0; Pos < Size; ++Pos) { + if (PatternStr[Pos] != '\\' || Pos + 1 == Size || + (PatternStr[Pos + 1] != '\\' && PatternStr[Pos + 1] != 'n')) { + continue; + } + + ParsedStr += PatternStr.substr(Prev, Pos - Prev); + // We explicitly skip over pairs of backslashes, so that the second '\' in + // "\\n" does not get used to form a newline character. + if (PatternStr[Pos + 1] == '\\') + ParsedStr += "\\\\"; + else + ParsedStr += '\n'; + + ++Pos; + Prev = Pos + 1; + } + + ParsedStr += PatternStr.substr(Prev, Size - Prev); + return ParsedStr; +} + /// Parses the given string into the Pattern. /// /// \p Prefix provides which prefix is being matched, \p SM provides the @@ -220,7 +253,11 @@ RegExStr += '('; ++CurParen; - if (AddRegExToRegEx(PatternStr.substr(2, End - 2), CurParen, SM)) + std::string ParsedStr = PatternStr.substr(2, End - 2); + if (MatchNewLineChars) + ParsedStr = ParseNewLineCharacters(ParsedStr); + + if (AddRegExToRegEx(ParsedStr, CurParen, SM)) return true; RegExStr += ')';