mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Introduce support for parsing declaration attributes that occur within
example:
#if hasAttribute(frozen)
@frozen
#endif
public struct X { ... }
will apply to "frozen" attribute to the struct `X`, but only when the
compiler supports the "frozen" attribute.
Correctly determining whether a particular `#if` block contains
attributes to be associated with the following declaration vs.
starting a new declaration requires arbitrary lookahead. The parser
will ensure that at least one of the branches of the `#if` contains an
attribute, and that none of the branches contains something that does
not fit the attribute grammar, before committing to parsing the `#if`
clause as part of the declaration attributes. This lookahead does
occur at the top level (e.g., in the parsing of top-level declarations
and code), but should only need to scan past the first `#if` line to
the following token in the common case.
Unlike other `#if` when used to wrap statements or declarations, we
make no attempt to record the `#if` not taken anywhere in the AST.
This reflects a change in attitude in the design of the AST, because
we have found that trying to represent this information there (e.g.,
via `IfConfigDecl`) complicates clients while providing little value.
This information is best kept in the syntax tree, only.
95 lines
1.3 KiB
Swift
95 lines
1.3 KiB
Swift
// RUN: %target-typecheck-verify-swift
|
|
|
|
#if hasAttribute(foo)
|
|
@foo(this is gibberish)
|
|
#endif
|
|
struct S1 { }
|
|
|
|
@frozen
|
|
#if hasAttribute(foo)
|
|
@foo
|
|
#endif
|
|
public struct S2 { }
|
|
|
|
#if hasAttribute(foo)
|
|
@foo
|
|
#endif
|
|
@inlinable
|
|
func f1() { }
|
|
|
|
#if hasAttribute(foo)
|
|
@foo
|
|
#else
|
|
@available(*, deprecated, message: "nope")
|
|
@frozen
|
|
#endif
|
|
public struct S3 { }
|
|
|
|
// Nested #if
|
|
#if hasAttribute(foo)
|
|
@foo
|
|
#elseif hasAttribute(available)
|
|
@available(*, deprecated, message: "nope")
|
|
#if hasAttribute(frozen)
|
|
@frozen
|
|
#endif
|
|
#endif
|
|
public struct S4 { }
|
|
|
|
// Nested in a type
|
|
struct Inner {
|
|
#if hasAttribute(foo)
|
|
@foo(this is gibberish)
|
|
#endif
|
|
struct S1 { }
|
|
|
|
@frozen
|
|
#if hasAttribute(foo)
|
|
#if hasAttribute(bar)
|
|
@foo @bar
|
|
#endif
|
|
#endif
|
|
public struct S2 { }
|
|
|
|
#if hasAttribute(foo)
|
|
@foo
|
|
#endif
|
|
@inlinable
|
|
func f1() { }
|
|
|
|
#if hasAttribute(foo)
|
|
@foo
|
|
#else
|
|
@available(*, deprecated, message: "nope")
|
|
@frozen
|
|
#endif
|
|
public struct S3 { }
|
|
}
|
|
|
|
// Nested in a function
|
|
func f2() {
|
|
#if hasAttribute(foo)
|
|
@foo(this is gibberish)
|
|
#endif
|
|
struct S1 { }
|
|
|
|
@available(*, deprecated)
|
|
#if hasAttribute(foo)
|
|
@foo
|
|
#endif
|
|
struct S2 { }
|
|
|
|
#if hasAttribute(foo)
|
|
@foo
|
|
#endif
|
|
@available(*, deprecated)
|
|
func f1() { }
|
|
|
|
#if hasAttribute(foo)
|
|
@foo
|
|
#else
|
|
@available(*, deprecated, message: "nope")
|
|
#endif
|
|
struct S3 { }
|
|
}
|