Fixes:
https://bugs.swift.org/browse/SR-3455https://bugs.swift.org/browse/SR-3663https://bugs.swift.org/browse/SR-4032https://bugs.swift.org/browse/SR-4031
Now, compilation conditions are validated at first, then evaluated. Also,
in non-Swift3 mode, '&&' now has higher precedence than '||'.
'A || B && C || D' are evaluated as 'A || (B && C) || D'.
Swift3 source breaking changes:
* [SR-3663] This used to be accepted and evaluate to 'true' because of short
circuit without any validation.
#if true || true * 12 = try Anything is OK?
print("foo")
#endif
In this change, remaining expressions are properly validated and
diagnosed if it's invalid.
* [SR-4031] Compound name references are now diagnosed as errors.
e.g. `#if os(foo:bar:)(macOS)` or `#if FLAG(x:y:)`
Swift3 compatibility:
* [SR-3663] The precedence of '||' and '&&' are still the same and the
following code evaluates to 'true'.
#if false || true && false
print("foo")
#endif
A lot of files transitively include Expr.h, because it was
included from SILInstruction.h, SILLocation.h and SILDeclRef.h.
However in reality most of these files don't do anything
with Exprs, especially not anything in IRGen or the SILOptimizer.
Now we're down to 171 files in the frontend which depend on
Expr.h, which is still a lot but much better than before.
This reverts the contents of #5778 and replaces it with a far simpler
implementation of condition resolution along with canImport. When
combined with the optimizations in #6279 we get the best of both worlds
with a performance win and a simpler implementation.
This completely removes Parse’s ability to make any judgement calls
about compilation conditions, instead the parser-relevant parts of
‘evaluateConditionalCompilationExpr’ have been moved into
‘classifyConditionalCompilationExpr’ where they exist to make sure only
decls that we want to parse actually parse later.
The condition-evaluation parts have been moved into NameBinding in the
form of a Walker that evaluates and collapses IfConfigs. This walker
is meant as an homage to PlaygroundLogger. It should probably be
factored out into a common walker at some point in the future.
Implemented in the naive way by way of the current ASTContext’s
‘LoadedModules’. In theory this list should be in one-to-one
correspondence with the definition of “importable” as any module that
is required for compilation is loaded *before* we start parsing the
file. This means we don’t have to load the module, just check that
it’s in the set of loaded modules.
Note that this approach will most likely fall apart if submodules are
introduced and are lazily loaded. At that point this will need to be
refactored into a format that defers the checking of conditions
sometime before or during typechecking (after namebinding).
...because "build configuration" is already the name of an Xcode feature.
- '#if' et al are "conditional compilation directives".
- The condition is a "conditional compilation expression", or just
"condition" if it's obvious.
- The predicates are "platform conditions" (including 'swift(>=...)')
- The options set with -D are "custom conditional compilation flags".
(Thanks, Kevin!)
I left "IfConfigDecl" as is, as well as SourceKit's various "BuildConfig"
settings because some of them are part of the SourceKit request format.
We can change these in follow-up commits, or not.
rdar://problem/19812930
Introduce a new "swift" build configuration that guards declarations
and statements with a language version - if the current language version
of the compiler is at least that version, the block will parse as normal.
For inactive blocks, the code will not be parsed an no diagnostics will
be emitted there.
Example:
#if swift(>=2.2)
print("Active")
#else
this code will not parse or emit diagnostics
#endif
https://github.com/apple/swift-evolution/blob/master/proposals/0020-if-swift-version.md
rdar://problem/19823607
r32195 introduced new behavior when there was an error with a build
config: if there was an error, never parse. This was to prevent noise
when a block of code guarded by a _compiler_version clause was
syntatically wrong/misspelled, making it active when it shouldn't have
been. This supressed parsing blocks guarded by other build configs,
which is kind of a regression since, until _compiler_version, all build
configs were always parsed, even if their clauses are inactive. Skipping
parsing may hinder indentation, code folding, and parse-aware
highlighting.
If there is a valid switch on _compiler_version, continue to
skip parsing and supress Lex diagnostics for inactive blocks. If there
is an error evaluating a build config, parse all of its blocks.
rdar://problem/22730282
Swift SVN r32205
This configuration clause will suppress lex diagnostics and skip parsing
altogether if the code under the clause isn't active - the compiler must
have a repository version greater than or equal to the version given to
_compiler_version.
This option is only meant to be used sparingly and not to track the
Swift *language* version.
Example, if using a compiler versioned 700.0.28:
#if _compiler_version("700.0.23")
print("This code will compile for versions 700.0.23 and later.")
#else
This + code + will + not + be + parsed
#endif
Included are new diagnostics for checking that the version is formatted
correctly and isn't empty.
New tests:
- Compiler version comparison unit tests
- Build configuration diagnostics
- Skipping parsing of code under inactive clauses
rdar://problem/22730282
Swift SVN r32195
This finally fixes a few code completion test cases.
This also regresses the error message in one parsing testcase because
previously we would just happily skip those tokens, but now error handling path
is a little bit different and these tokens hit different error handling code.
This can be fixed by parsing a tuple for the selector argument and complaining
if the tuple had more than one element.
Swift SVN r7389
This will allow us to do code completion inside lists (e.g., tuples) *and* get
parser recovery instead of stopping at the code completion token immediately.
Swift SVN r7366
This allows the parser to recover, create an AST node, return it to the caller
*and* signal the caller that there was an error to trigger recovery in the
caller. Until now the error was signalled with a nullptr result (any non-null
result was considered a success and no recovery was done in that case).
This also allows us to signal the caller if there was a code completion token
inside the production we tried to parse to trigger delayed parsing in the
caller while doing recovery in the callee. Until now we could not do recovery
in the callee so that the caller could find the code completion token.
Right now we don't take any advantage of these features. This commit just
replaces some uses of NullablePtr with ParserResult.
Swift SVN r7332