Files
swift-mirror/test/attr/conditional_attribute.swift
Doug Gregor b3c5fde118 Parse declaration attributes within #if...#endif blocks.
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.
2022-07-25 21:31:17 -04:00

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 { }
}