Since commit v3.4.0-rc1~321^2~2 (Genex: Store a backtrace, not a pointer
to one, 2015-07-08) we treat cmListFileBacktrace instances as
lightweight values. This was true at the time only because the
backtrace information was kept in the cmState snapshot hierarchy.
However, that forced us to accumulate a lot of otherwise short-lived
snapshots just to have the backtrace fields available for reference by
cmListFileBacktrace instances. Recent refactoring made backtrace
instances independent of the snapshot hierarchy to avoid accumulating
short-lived snapshots. This came at the cost of making backtrace values
heavy again, leading to lots of string coying and slower execution.
Fix this by refactoring cmListFileBacktrace to provide value semantics
with efficient shared storage underneath. Teach cmMakefile to maintain
its call stack using an instance of cmListFileBacktrace. This approach
allows the current backtrace to be efficiently saved whenever it is
needed.
Also teach cmListFileBacktrace the notion of a file-level scope. This
is useful for messages about the whole file (e.g. during parsing) that
are not specific to any line within it. Push the CMakeLists.txt scope
for each directory and never pop it. This ensures that we always have
some context information and simplifies cmMakefile::IssueMessage.
Push/pop a file-level scope as each included file is processed. This
supersedes cmParseFileScope and improves diagnostic message context
information in a few places. Fix the corresponding test cases to expect
the improved output.
The fix in commit v3.2.3~3^2 (Fix assertion failure on unmatched foreach
in function, 2015-05-18) broke handling of unmatched non-loop blocks
because it assumed all function blockers removed during error unwinding
were for loops, essentially switching the set of mishandled cases.
The purpose of the loop block push/pop operations is to define a scope
matching the lifetime of the loop function blockers. Since our function
blockers already have the proper lifetime, simply move the push/pop
operations to their constructor/destructor.
Extend the RunCMake.Syntax test with a case covering this.
The lexical scope counting added by commit v3.2.0-rc1~332^2~1 (Track
nested loop levels in CMake language with a stack of counters,
2014-11-18) forgot to account for scopes popped by error messages about
unclosed scopes. Teach the error handler to pop the lexical scope it
reports as unclosed. Re-order the lexical scope RAII object to be
inside the variable scope RAII object scope so that the lexical scope
is fully closed before we check assertions about variable scopes.
Extend the RunCMake.Syntax test with a case covering this.
The lexer changes in commit v3.0.0-rc1~495^2 (Add Lua-style long
brackets and long comments to CMake language, 2013-08-06) accidentally
left out matching '[' as a single character in an unquoted argument.
Add a lexer rule to match it and extend the RunCMake.Syntax test to
cover this case.
Include tests for:
- @ expansion during normal execution
- various characters in variable names for comparison between the new
and the old parser
- corner cases in the parsers
- correct messages when behavior is different
There are some corner cases in variable expansion which would be nice to
capture before going and rewriting the variable expansion code. The
majority of these are related to configuring files and strings with '@'
in them in conjunction with @ONLY being specified. Another is testing
for '(' usage inside of ENV variable references based on whether it is
quoted or not.
Bracket arguments recorded in command invocations inside foreach,
function, and macro blocks should not have any replacements done when
the arguments are replayed later. Teach the RunCMake.Syntax test to
cover these cases.
Add an Escape1 test case covering \-escape cases inside bracket, quoted,
and unquoted arguments. Also cover comments immediately after quoted
and unquoted arguments on lines containing \# escapes.
Teach the CMake language lexer to treat the \-LF pair terminating a
line ending in an odd number of backslashes inside a quoted argument
as a continuation. Drop the pair from the returned quoted argument
token text. This will allow long lines inside quoted argument
strings to be divided across multiple lines in the source file.
It will also allow quoted argument text to start on the line after
the opening quote. For example, the code:
set(x "\
...")
sets variable "x" to the value "..." with no opening newline.
Previously an odd number of backslashes at the end of a line inside
a quoted argument would put a \-LF pair (or a \-CR pair) literally
in the argument. Then the command-argument evaluator would complain
that the \-escape sequence is invalid. Therefore this syntax is
available to use without changing behavior of valid existing code.
Teach the RunCMake.Syntax test to cover cases of quoted arguments
with lines ending in \, \\, and \\\. Odd counts are continuations.
Teach the CMake language parser to recognize Lua-style "long bracket"
arguments. These start with two '[' separated by zero or more '='
characters e.g. "[[" or "[=[" or "[==[". They end with two ']'
separated by the same number of '=' as the opening bracket. There is no
nesting of brackets of the same level (number of '='). No escapes,
variable expansion, or other processing is performed on the content
between such brackets so they always represent exactly one argument.
Also teach CMake to parse and ignore "long comment" syntax. A long
comment starts with "#" immediately followed by an opening long bracket.
It ends at the matching close long bracket.
Teach the RunCMake.Syntax test to cover long bracket and long comment
cases.
Read input files in binary mode instead of text mode and convert CRLF
newlines to LF newlines explicitly in our own buffer. This is necessary
to read CMake source files with CRLF newlines on platforms whose C
runtime libraries do not transform newlines in text mode. For example,
a Cygwin or Linux binary may not transform CRLF -> LF in files read from
a Windows filesystem. Perform the conversion ourselves to ensure that
multi-line string literals in CMake source files have LF newlines
everywhere.
Teach the lexer to read a UTF-8, UTF-16 BE/LE, or UTF-32 BE/LE
Byte-Order-Mark from the start of a file if any is present. Report an
error on files using UTF-16 or UTF-32 and accept a UTF-8 or missing BOM.
Teach the lexer to treat a single letter as an identifier instead of an
unquoted argument. Outside of a command invocation, the parser treats
an identifier as a command name and an unquoted argument as an error.
Inside of a command invocation, the parser treats an identifier as an
unquoted argument. Therefore this change to the lexer will make what
was previously an error case work with no other behavioral change.
Since commit 58e52416 (Warn about arguments not separated by whitespace,
2013-02-16) we warn about arguments not separated by spaces. Loosen the
warning to not complain about left parens not separated by spaces from
the preceding token. This is common in code like "if(NOT(X))".
Teach the RunCMake.Syntax test to cover cases of left parens not
separated by spaces and check that no warning appears.
In the future CMake will introduce Lua-style long bracket syntax.
Warn about unquoted arguments that in the future will be treated
as opening long brackets.
Teach the RunCMake.Syntax test to cover such cases and ensure that the
warning appears.
Teach the lexer to return tokens for whitespace. Teach the parser to
tolerate the space tokens where whitespace is allowed. Also teach the
parser to diagnose and warn about cases of quoted arguments followed
immediately by another argument. This was accidentally allowed
previously, so we only warn.
Update the RunCMake.Syntax test case StringNoSpace expected stderr to
include the warnings.
If a line inside a string ends in a backslash count the following
newline character as a line increment. Add a test covering this case to
verify that subsequent line numbers are correct.
Test basic unquoted and quoted argument parsing cases including failure
on an unterminated string and an unterminated command invocation. Also
cover arguments not separated by any spaces, which is accidentally
allowed by the current parser.