// REQUIRES: swift_swift_parser, executable_test // RUN: %empty-directory(%t) // RUN: %host-build-swift -swift-version 5 -emit-library -o %t/%target-library-name(MacroDefinition) -module-name=MacroDefinition %S/Inputs/syntax_macro_definitions.swift // Diagnostics testing // RUN: %target-typecheck-verify-swift -swift-version 5 -load-plugin-library %t/%target-library-name(MacroDefinition) -module-name MacroUser -DTEST_DIAGNOSTICS // Diagnostics testing by importing macros from a module // RUN: %target-swift-frontend -swift-version 5 -emit-module -o %t/freestanding_macro_library.swiftmodule %S/Inputs/freestanding_macro_library.swift -module-name freestanding_macro_library -load-plugin-library %t/%target-library-name(MacroDefinition) // RUN: %target-swift-frontend -swift-version 5 -emit-module -o %t/freestanding_macro_library_2.swiftmodule %S/Inputs/freestanding_macro_library_2.swift -module-name freestanding_macro_library_2 -load-plugin-library %t/%target-library-name(MacroDefinition) -I %t // RUN: %target-typecheck-verify-swift -swift-version 5 -load-plugin-library %t/%target-library-name(MacroDefinition) -module-name MacroUser -DTEST_DIAGNOSTICS -I %t -DIMPORT_MACRO_LIBRARY // RUN: not %target-swift-frontend -swift-version 5 -typecheck -load-plugin-library %t/%target-library-name(MacroDefinition) -module-name MacroUser -DTEST_DIAGNOSTICS -serialize-diagnostics-path %t/macro_expand.dia %s -emit-macro-expansion-files no-diagnostics -Rmacro-loading > %t/macro-printing.txt // RUN: c-index-test -read-diagnostics %t/macro_expand.dia 2>&1 | %FileCheck -check-prefix CHECK-DIAGS -dump-input=always %s // RUN: %FileCheck %s --check-prefix CHECK-MACRO-PRINTED < %t/macro-printing.txt // RUN: not %target-swift-frontend -swift-version 5 -typecheck -diagnostic-style=swift -load-plugin-library %t/%target-library-name(MacroDefinition) -module-name MacroUser -DTEST_DIAGNOSTICS %s > %t/pretty-macro-diagnostics.txt 2>&1 // RUN: %FileCheck %s --check-prefix PRETTY-DIAGS < %t/pretty-macro-diagnostics.txt // Debug info SIL testing // RUN: %target-swift-frontend -swift-version 5 -emit-sil -load-plugin-library %t/%target-library-name(MacroDefinition) %s -module-name MacroUser -o - -g | %FileCheck --check-prefix CHECK-SIL %s // Debug info IR testing // RUN: %target-swift-frontend -swift-version 5 -dwarf-version=4 -emit-ir -load-plugin-library %t/%target-library-name(MacroDefinition) %s -module-name MacroUser -o - -g | %FileCheck --check-prefix CHECK-IR-DWARF4 %s // RUN: %target-swift-frontend -swift-version 5 -dwarf-version=5 -emit-ir -load-plugin-library %t/%target-library-name(MacroDefinition) %s -module-name MacroUser -o - -g | %FileCheck --check-prefix CHECK-IR %s // Execution testing // RUN: %target-build-swift -swift-version 5 -g -load-plugin-library %t/%target-library-name(MacroDefinition) %s -o %t/main -module-name MacroUser -Xfrontend -emit-dependencies-path -Xfrontend %t/main.d -Xfrontend -emit-reference-dependencies-path -Xfrontend %t/main.swiftdeps // RUN: %target-codesign %t/main // RUN: %target-run %t/main | %FileCheck %s // Plugin search path and loaded module trace testing // RUN: %target-swift-frontend -swift-version 5 -emit-sil -plugin-path %t %s -module-name MacroUser -emit-loaded-module-trace -o %t/loaded_module_trace // RUN: %FileCheck -check-prefix=CHECK-MODULE-TRACE %s < %t/loaded_module_trace.trace.json // CHECK-MODULE-TRACE: {{libMacroDefinition.dylib|libMacroDefinition.so|MacroDefinition.dll}} // CHECK-DIAGS: loaded macro implementation module 'MacroDefinition' from shared library #if IMPORT_MACRO_LIBRARY import freestanding_macro_library import freestanding_macro_library_2 #else @freestanding(declaration, names: named(StructWithUnqualifiedLookup)) macro structWithUnqualifiedLookup() = #externalMacro(module: "MacroDefinition", type: "DefineStructWithUnqualifiedLookupMacro") @freestanding(declaration) macro anonymousTypes(_: () -> String) = #externalMacro(module: "MacroDefinition", type: "DefineAnonymousTypesMacro") @freestanding(declaration) macro freestandingWithClosure(_ value: T, body: (T) -> T) = #externalMacro(module: "MacroDefinition", type: "EmptyDeclarationMacro") @freestanding(declaration, names: arbitrary) macro bitwidthNumberedStructs(_ baseName: String) = #externalMacro(module: "MacroDefinition", type: "DefineBitwidthNumberedStructsMacro") @freestanding(expression) macro stringify(_ value: T) -> (T, String) = #externalMacro(module: "MacroDefinition", type: "StringifyMacro") @freestanding(declaration, names: arbitrary) macro bitwidthNumberedStructs(_ baseName: String, blah: Bool) = #externalMacro(module: "MacroDefinition", type: "DefineBitwidthNumberedStructsMacro") @freestanding(declaration, names: named(value)) macro varValue() = #externalMacro(module: "MacroDefinition", type: "VarValueMacro") #endif @freestanding(declaration, names: named(storedProperty)) public macro AddStoredProperty(_ x: T) = #externalMacro(module: "MacroDefinition", type: "StoredPropertyMacro") #if TEST_DIAGNOSTICS @freestanding(declaration) macro NotCovered() = #externalMacro(module: "MacroDefinition", type: "InvalidMacro") struct MemberNotCovered { #NotCovered // expected-note@-1 {{in expansion of macro 'NotCovered' here}} /* expected-expansion@-3:3 {{ expected-error@1:5{{declaration name 'value' is not covered by macro 'NotCovered'}} }} */ } @attached(peer) macro Invalid() = #externalMacro(module: "MacroDefinition", type: "InvalidMacro") @Invalid struct Bad {} // expected-note@-2 18 {{in expansion of macro 'Invalid' on struct 'Bad' here}} /* expected-expansion@-3:14 {{ expected-error@1:8{{macro expansion cannot introduce import}} expected-error@3:17{{macro expansion cannot introduce precedence group}} expected-error@6:25{{macro 'myMacro()' requires a definition}} expected-error@6:25{{macro expansion cannot introduce macro}} expected-error@8:1{{macro expansion cannot introduce extension}} expected-error@11:1{{macro expansion cannot introduce '@main' type}} expected-error@12:8{{declaration name 'MyMain' is not covered by macro 'Invalid'}} expected-error@17:11{{declaration name 'Array' is not covered by macro 'Invalid'}} expected-error@19:11{{declaration name 'Dictionary' is not covered by macro 'Invalid'}} expected-error@21:11{{macro expansion cannot introduce default literal type 'BooleanLiteralType'}} expected-error@23:11{{macro expansion cannot introduce default literal type 'ExtendedGraphemeClusterType'}} expected-error@25:11{{macro expansion cannot introduce default literal type 'FloatLiteralType'}} expected-error@27:11{{macro expansion cannot introduce default literal type 'IntegerLiteralType'}} expected-error@29:11{{macro expansion cannot introduce default literal type 'StringLiteralType'}} expected-error@31:11{{macro expansion cannot introduce default literal type 'UnicodeScalarType'}} expected-error@33:11{{macro expansion cannot introduce default literal type '_ColorLiteralType'}} expected-error@35:11{{macro expansion cannot introduce default literal type '_ImageLiteralType'}} expected-error@37:11{{macro expansion cannot introduce default literal type '_FileReferenceLiteralType'}} }} */ // CHECK-DIAGS: CONTENTS OF FILE @__swiftmacro_9MacroUser3Bad7InvalidfMp_.swift // CHECK-DIAGS: import Swift // CHECK-DIAGS: precedencegroup MyPrecedence { // CHECK-DIAGS: } // CHECK-DIAGS: @attached(member) macro myMacro() // CHECK-DIAGS: extension Int { // CHECK-DIAGS: } // CHECK-DIAGS: @main // CHECK-DIAGS: struct MyMain { // CHECK-DIAGS: static func main() { // CHECK-DIAGS: } // CHECK-DIAGS: } // CHECK-DIAGS: typealias Array = Void // CHECK-DIAGS: typealias Dictionary = Void // CHECK-DIAGS: typealias BooleanLiteralType = Void // CHECK-DIAGS: typealias ExtendedGraphemeClusterType = Void // CHECK-DIAGS: typealias FloatLiteralType = Void // CHECK-DIAGS: typealias IntegerLiteralType = Void // CHECK-DIAGS: typealias StringLiteralType = Void // CHECK-DIAGS: typealias UnicodeScalarType = Void // CHECK-DIAGS: typealias _ColorLiteralType = Void // CHECK-DIAGS: typealias _ImageLiteralType = Void // CHECK-DIAGS: typealias _FileReferenceLiteralType = Void // CHECK-DIAGS: END CONTENTS OF FILE class HasStoredPropertyClassInvalid { #AddStoredProperty((Self.self, 0).1) // expected-note {{in expansion of macro 'AddStoredProperty' here}} /* expected-expansion@-2:3 {{ expected-error@1:22{{covariant 'Self' type cannot be referenced from a stored property initializer}} }} */ } // Redeclaration checking should behave as though expansions are part of the // source file. struct RedeclChecking { #varValue /* expected-expansion@-2:3 {{ expected-note@1:5{{'value' previously declared here}} }} */ // expected-error@+1 {{invalid redeclaration of 'value'}} var value: Int { 0 } } // CHECK-DIAGS: CONTENTS OF FILE @__swiftmacro_9MacroUser0023macro_expandswift_elFCffMX[[@LINE-12]]_2_33_4361AD9339943F52AE6186DD51E04E91Ll8varValuefMf_.swift: // CHECK-DIAGS: var value: Int { // CHECK-DIAGS: 1 // CHECK-DIAGS: } // CHECK-DIAGS: END CONTENTS OF FILE @attached(body) public macro ThrowCancellation() = #externalMacro(module: "MacroDefinition", type: "ThrowCancellationMacro") // https://github.com/swiftlang/swift/issues/79039 - Make sure we diagnose the // error mismatch. @ThrowCancellation // expected-note {{in expansion of macro 'ThrowCancellation' on global function 'issue79039()' here}} func issue79039() throws(DecodingError) /* expected-expansion@-2:39 {{ expected-error@2:11{{thrown expression type 'CancellationError' cannot be converted to error type 'DecodingError'}} }} */ @ThrowCancellation // expected-note {{in expansion of macro 'ThrowCancellation' on global function 'issue79039_2()' here}} func issue79039_2() throws(DecodingError) {} /* expected-expansion@-2:43 {{ expected-error@2:11{{thrown expression type 'CancellationError' cannot be converted to error type 'DecodingError'}} }} */ #endif @freestanding(declaration) macro accidentalCodeItem() = #externalMacro(module: "MacroDefinition", type: "FakeCodeItemMacro") @attached(peer) macro AccidentalCodeItem() = #externalMacro(module: "MacroDefinition", type: "FakeCodeItemMacro") #if TEST_DIAGNOSTICS func invalidDeclarationMacro() { #accidentalCodeItem // expected-note@-1 {{in expansion of macro 'accidentalCodeItem' here}} /* expected-expansion@-3:3 {{ expected-error@1:1{{expected macro expansion to produce a declaration}} }} */ @AccidentalCodeItem struct S {} // expected-note@-1 {{in expansion of macro 'AccidentalCodeItem' on struct 'S' here}} /* expected-expansion@-3:34 {{ expected-error@1:1{{expected macro expansion to produce a declaration}} }} */ do { @AccidentalCodeItem struct S {} // expected-note@-1 {{in expansion of macro 'AccidentalCodeItem' on struct 'S' here}} /* expected-expansion@-3:36 {{ expected-error@1:1{{expected macro expansion to produce a declaration}} }} */ } } #endif @freestanding(expression) macro customFileID() -> String = #externalMacro(module: "MacroDefinition", type: "FileIDMacro") @freestanding(expression) macro fileID() -> T = #externalMacro(module: "MacroDefinition", type: "FileIDMacro") @freestanding(expression) macro recurse(_: Bool) = #externalMacro(module: "MacroDefinition", type: "RecursiveMacro") @freestanding(expression) macro assert(_: Bool) = #externalMacro(module: "MacroDefinition", type: "AssertMacro") func testFileID(a: Int, b: Int) { // CHECK: MacroUser/macro_expand.swift print("Result is \(#customFileID)") // CHECK-SIL: sil_scope [[SRC_SCOPE:[0-9]+]] { loc "{{.*}}macro_expand.swift":[[@LINE-3]]:6 parent {{.*}}testFileID // CHECK-SIL: sil_scope [[EXPANSION_SCOPE:[0-9]+]] { loc "{{.*}}macro_expand.swift":[[@LINE-2]]:22 parent [[SRC_SCOPE]] // CHECK-SIL: sil_scope [[MACRO_SCOPE:[0-9]+]] { loc "@__swiftmacro{{.*}}":1:1 parent @$s9MacroUser0023macro_expandswift_elFCffMX{{.*}}_12customFileIDfMf_ {{.*}} inlined_at [[EXPANSION_SCOPE]] } // CHECK-SIL: string_literal utf8 "MacroUser/macro_expand.swift", loc "@__swiftmacro_9MacroUser0023macro_expandswift_elFCffMX{{.*}}_12customFileIDfMf_.swift":1:1, scope [[MACRO_SCOPE]] // CHECK-IR-DAG: !DISubprogram(name: "customFileID", linkageName: "$s9MacroUser0023macro_expandswift_elFCffMX{{.*}}_12customFileIDfMf_" // CHECK: Builtin result is MacroUser/macro_expand.swift // CHECK-AST: macro_expansion_expr type='String'{{.*}}name=line print("Builtin result is \(#fileID)") print( // CHECK-IR-DAG: ![[L1:[0-9]+]] = distinct !DILocation(line: [[@LINE+4]], column: 5 // CHECK-IR-DAG: ![[L2:[0-9]+]] = distinct !DILocation({{.*}}inlinedAt: ![[L1]]) // CHECK-IR-DAG: !DIFile(filename: "{{.*}}@__swiftmacro_9MacroUser0023macro_expandswift_elFCffMX{{.*}}_12customFileIDfMf_.swift", {{.*}}source: "{{.*}}MacroUser/macro_expand.swift{{.*}}// original-source-range: {{.*}}") // CHECK-IR-DWARF4: {{(target triple = .*-unknown-windows-msvc)|(!DIFile\(filename: ".*generated-.*@__swiftmacro_9MacroUser0023macro_expandswift_elFCffMX.*_12customFileIDfMf_.swift", directory: "[^"]*"\))}} #addBlocker( #stringify(a - b) ) ) } testFileID(a: 1, b: 2) @freestanding(expression) macro stringifyAndTry(_ value: T) -> (T, String) = #externalMacro(module: "MacroDefinition", type: "StringifyAndTryMacro") enum Angle { case degrees(Double) case radians(Double) } func testStringify(a: Int, b: Int) { let s = #stringify(a + b) print(s) // CHECK-AST: macro_expansion_expr type='(Int, String)'{{.*}}name=stringify // CHECK-AST-NEXT: argument_list // CHECK-AST: tuple_expr type='(Int, String)' location=Macro expansion of #stringify let (b, s2) = #stringify({ () -> Bool in return true }) // CHECK-AST: macro_expansion_expr type='(() -> Bool, String)'{{.*}}name=stringify // CHECK-AST-NEXT: argument_list // CHECK-AST: tuple_expr type='(() -> Bool, String)' location=Macro expansion of #stringify let (b2, s3) = #stringify(1 + 2) // CHECK-AST: macro_expansion_expr type='(Double, String)'{{.*}}name=stringify // CHECK-AST-NEXT: argument_list // CHECK-AST: tuple_expr type='(Double, String)' location=Macro expansion of #stringify _ = (b, b2, s2, s3) let angle = Angle.degrees(17) switch angle { case .degrees(let value): _ = #stringify(value) case .radians(let value): _ = #stringify(value) } } func testAssert(a: Int, b: Int) { #assert(a == b) } public struct Outer { var value: Int = 0 public func test() { let (a, b) = #stringify(1 + value) let (c, d) = #stringify({ x in x + 1 }) _ = a _ = b _ = c _ = d } } // CHECK: (2, "a + b") testStringify(a: 1, b: 1) protocol P { } extension Int: P { } // Stringify with closures that have local types. @available(SwiftStdlib 5.1, *) func testStringifyWithLocalTypes() { _ = #stringify({ struct LocalType: P { static var name: String = "Taylor" var something: some P { self } } func f() -> some P { return LocalType().something } }) } // Stringify in closures that have anonymous parameters. func testStringifyWithAnonymousParameters() { { _ = #stringify($0 + $1) }(1, 2) } func maybeThrowing() throws -> Int { 5 } #if TEST_DIAGNOSTICS @freestanding(expression) @discardableResult macro discardableStringify(_ value: T) -> (T, String) = #externalMacro(module: "MacroDefinition", type: "StringifyMacro") func testDiscardableStringify(x: Int) { #stringify(x + 1) // expected-warning{{expression of type '(Int, String)' is unused}} #discardableStringify(x + 1) } #endif #if TEST_DIAGNOSTICS // This causes an error when non-'Bool' value is passed. @freestanding(expression) macro assertAny(_ value: T) = #externalMacro(module: "MacroDefinition", type: "AssertMacro") func testNested() { struct Nested { } _ = #stringify(#assertAny(Nested())) // expected-note@-1 {{in expansion of macro 'stringify' here}} /* expected-expansion@-3:7 {{ expected-note@1:2{{in expansion of macro 'assertAny' here}} expected-expansion@1:2{{ expected-error@1:8{{cannot convert value of type 'Nested' to expected argument type 'Bool'}} }} }} */ // PRETTY-DIAGS: 1:8: error: cannot convert value of type 'Nested' to expected argument type 'Bool' // PRETTY-DIAGS: macro_expand.swift:{{.*}}:39: note: expanded code originates here // PRETTY-DIAGS: --- macro expansion #stringify // PRETTY-DIAGS: --- macro expansion #assertAny // PRETTY-DIAGS-NEXT: 1 | assert(Nested()) // PRETTY-DIAGS-NEXT: | `- error: cannot convert value } #endif func testStringifyWithThrows() throws { // Okay, we can put the try inside or outside _ = try #stringify(maybeThrowing()) _ = #stringify(try maybeThrowing()) #if TEST_DIAGNOSTICS // FIXME: Lots of duplicate notes here _ = #stringify(maybeThrowing()) // expected-note 4{{in expansion of macro 'stringify' here}} /* expected-expansion@-2:7 {{ expected-error@1:2{{call can throw but is not marked with 'try'}} expected-note@1:2{{did you mean to disable error propagation?}} expected-note@1:2{{did you mean to handle error as optional value?}} expected-note@1:2{{did you mean to use 'try'?}} }} */ #endif // The macro adds the 'try' for us. _ = #stringifyAndTry(maybeThrowing()) } @available(SwiftStdlib 5.1, *) func throwingFunc() async throws -> Int { 5 } @freestanding(expression) macro callThrowingFunc(_ body: () -> T) -> T = #externalMacro(module: "MacroDefinition", type: "TryCallThrowingFuncMacro") @available(SwiftStdlib 5.1, *) func testThrowingCall() async throws -> Int { #callThrowingFunc { [1, 2, 3, 4, 5].map { $0 + 1 }.first! } } func testStringifyWithLocalType() throws { _ = #stringify({ struct QuailError: Error {} throw QuailError() }) } @freestanding(expression) macro addBlocker(_ value: T) -> T = #externalMacro(module: "MacroDefinition", type: "AddBlocker") struct OnlyAdds { static func +(lhs: OnlyAdds, rhs: OnlyAdds) -> OnlyAdds { lhs } } func testAddBlocker(a: Int, b: Int, c: Int, oa: OnlyAdds) { _ = #addBlocker(a * b * c) #if TEST_DIAGNOSTICS _ = #addBlocker(a + b * c) // expected-error{{blocked an add; did you mean to subtract? (from macro 'addBlocker')}} // expected-note@-1{{use '-'}}{{21-22=-}} _ = #addBlocker(oa + oa) // expected-error{{blocked an add; did you mean to subtract? (from macro 'addBlocker')}} // expected-note@-1{{in expansion of macro 'addBlocker' here}} // expected-note@-2{{use '-'}}{{22-23=-}} /* expected-expansion@-4:7 {{ expected-error@1:4{{binary operator '-' cannot be applied to two 'OnlyAdds' operands}} }} */ _ = #addBlocker({ // expected-note{{in expansion of macro 'addBlocker' here}} /* expected-expansion@-2:7 {{ expected-error@9:16{{referencing operator function '-' on 'FloatingPoint' requires that 'OnlyAdds' conform to 'FloatingPoint'}} }} */ print("hello") print(oa + oa) // expected-error{{blocked an add; did you mean to subtract? (from macro 'addBlocker')}} // expected-note@-1{{use '-'}} print(oa + oa) // expected-error{{blocked an add; did you mean to subtract? (from macro 'addBlocker')}} // expected-note@-1{{use '-'}} }()) // Check recursion. #recurse(false) // okay #recurse(true) /* expected-expansion@-2:3 {{ expected-error@1:1{{recursive expansion of macro 'recurse'}} }} expected-note@-5{{in expansion of macro 'recurse' here}} */ #endif } @freestanding(expression) macro leftHandOperandFinder(_ value: T) -> T = #externalMacro(module: "MacroDefinition", type: "LeftHandOperandFinderMacro") // Test source location information. func testSourceLocations(x: Int, yolo: Int, zulu: Int) { // CHECK-MACRO-PRINTED: Source range for LHS is "MacroUser/macro_expand.swift": [[@LINE+3]]:5-[[@LINE+3]]:13 // CHECK-MACRO-PRINTED: Source range for LHS is "MacroUser/macro_expand.swift": [[@LINE+2]]:5-[[@LINE+2]]:6 _ = #leftHandOperandFinder( x + yolo + zulu ) } // Make sure we don't crash with declarations produced by expansions. @freestanding(expression) macro nestedDeclInExpr() -> () -> Void = #externalMacro(module: "MacroDefinition", type: "NestedDeclInExprMacro") func testNestedDeclInExpr() { let _: () -> Void = #nestedDeclInExpr } // Test non-arbitrary names @freestanding(declaration, names: named(A), named(B), named(foo), named(addOne)) macro defineDeclsWithKnownNames() = #externalMacro(module: "MacroDefinition", type: "DefineDeclsWithKnownNamesMacro") // Freestanding macros are not in inlined scopes. // CHECK-SIL: sil_scope {{.*}} { loc "@__swiftmacro_9MacroUser0023macro_expandswift_elFCffMX{{.*}}_25defineDeclsWithKnownNamesfMf_.swift"{{.*}} -> Int } // FIXME: Macros producing arbitrary names are not supported yet #if false #bitwidthNumberedStructs("MyIntGlobal") #bitwidthNumberedStructs("MyIntGlobalTwo", blah: false) let blah = false #bitwidthNumberedStructs("MyIntGlobalThree", blah: blah) #endif // Test unqualified lookup from within a macro expansion let world = 3 // to be used by the macro expansion below #structWithUnqualifiedLookup() _ = StructWithUnqualifiedLookup().foo() #anonymousTypes { "hello" } func testFreestandingMacroExpansion() { // Explicit structs to force macros to be parsed as decl. struct Foo { static let singleton = Foo() static let s2 = Foo.singleton #bitwidthNumberedStructs("MyIntOne") } // CHECK: MyIntOne8 print(Foo.MyIntOne8.self) // CHECK: MyIntOne16 print(Foo.MyIntOne16.self) // CHECK: MyIntOne32 print(Foo.MyIntOne32.self) // CHECK: MyIntOne64 print(Foo.MyIntOne64.self) struct Foo2 { #bitwidthNumberedStructs("MyIntTwo", blah: false) #defineDeclsWithKnownNames() } // CHECK: MyIntTwo8 print(Foo2.MyIntTwo8.self) // CHECK: MyIntTwo16 print(Foo2.MyIntTwo16.self) // CHECK: MyIntTwo32 print(Foo2.MyIntTwo32.self) // CHECK: MyIntTwo64 print(Foo2.MyIntTwo64.self) // CHECK: A print(Foo2.A.self) // CHECK: B print(Foo2.B.self) // CHECK: 1 print(Foo2().foo) // CHECK: 2 print(Foo2().addOne(1)) #if TEST_DIAGNOSTICS struct Foo3 { #bitwidthNumberedStructs("BUG", blah: false) // expected-note@-1 4{{in expansion of macro 'bitwidthNumberedStructs' here}} /* expected-expansion@-3:5 {{ expected-error@3:14{{unexpected non-void return value in void function}} expected-note@3:14{{did you mean to add a return type?}} expected-error@6:14{{unexpected non-void return value in void function}} expected-note@6:14{{did you mean to add a return type?}} }} */ // CHECK-DIAGS: CONTENTS OF FILE @__swiftmacro_9MacroUser0023macro_expandswift_elFCffMX{{.*}}_23bitwidthNumberedStructsfMf_.swift // CHECK-DIAGS: struct BUG { // CHECK-DIAGS: func $s9MacroUser0023macro_expandswift_elFCffMX{{.*}}_23bitwidthNumberedStructsfMf_6methodfMu_() // CHECK-DIAGS: func $s9MacroUser0023macro_expandswift_elFCffMX{{.*}}_23bitwidthNumberedStructsfMf_6methodfMu0{{_?}}() } #endif // FIXME: Arbitrary name lookup is not yet supported. // HECK: MyIntGlobal8 // print(MyIntGlobal8.self) // HECK: MyIntGlobal16 // print(MyIntGlobal16.self) // HECK: MyIntGlobal32 // print(MyIntGlobal32.self) // HECK: MyIntGlobal64 // print(MyIntGlobal64.self) #anonymousTypes { "hello" } } testFreestandingMacroExpansion() // Explicit structs to force macros to be parsed as decl. var globalBool = true struct ContainerOfNumberedStructs { #bitwidthNumberedStructs("MyIntOne") #bitwidthNumberedStructs("MyIntTwo", blah: globalBool) } // Avoid re-type-checking declaration macro arguments. func testFreestandingWithClosure(i: Int) { #freestandingWithClosure(i) { x in x } #freestandingWithClosure(i) { let x = $0 return x } } // Nested macros with closures @freestanding(expression) macro coerceToInt(_ value: T) -> Int = #externalMacro(module: "MacroDefinition", type: "CoerceToIntMacro") func testFreestandingClosureNesting() { _ = #stringify({ () -> Int in #coerceToInt(2) }) } // Freestanding declaration macros that produce local variables func testLocalVarsFromDeclarationMacros() { #varValue } // Variadic macro @freestanding(declaration, names: arbitrary) macro emptyDecl(_: String...) = #externalMacro(module: "MacroDefinition", type: "EmptyDeclarationMacro") struct TakesVariadic { #emptyDecl("foo", "bar") } // Funkiness with static functions introduced via macro expansions. @freestanding(declaration, names: named(foo())) public macro staticFooFunc() = #externalMacro(module: "MacroDefinition", type: "StaticFooFuncMacro") @freestanding(declaration, names: arbitrary) public macro staticFooFuncArbitrary() = #externalMacro(module: "MacroDefinition", type: "StaticFooFuncMacro") class HasAnExpandedStatic { #staticFooFunc() } class HasAnExpandedStatic2 { #staticFooFuncArbitrary() } func testHasAnExpandedStatic() { #if TEST_DIAGNOSTICS foo() // expected-error{{cannot find 'foo' in scope}} #endif } @freestanding(declaration, names: named(==)) public macro addSelfEqualsOperator() = #externalMacro(module: "MacroDefinition", type: "SelfAlwaysEqualOperator") @freestanding(declaration, names: arbitrary) public macro addSelfEqualsOperatorArbitrary() = #externalMacro(module: "MacroDefinition", type: "SelfAlwaysEqualOperator") @attached(member, names: named(==)) public macro AddSelfEqualsMemberOperator() = #externalMacro(module: "MacroDefinition", type: "SelfAlwaysEqualOperator") @attached(member, names: arbitrary) public macro AddSelfEqualsMemberOperatorArbitrary() = #externalMacro(module: "MacroDefinition", type: "SelfAlwaysEqualOperator") struct HasEqualsSelf { #addSelfEqualsOperator } struct HasEqualsSelf2 { #addSelfEqualsOperatorArbitrary } @AddSelfEqualsMemberOperator struct HasEqualsSelf3 { } @AddSelfEqualsMemberOperatorArbitrary struct HasEqualsSelf4 { } protocol SelfEqualsBoolProto { // expected-note 4{{where 'Self' =}} static func ==(lhs: Self, rhs: Bool) -> Bool } struct HasEqualsSelfP: SelfEqualsBoolProto { #addSelfEqualsOperator } struct HasEqualsSelf2P: SelfEqualsBoolProto { #addSelfEqualsOperatorArbitrary } @AddSelfEqualsMemberOperator struct HasEqualsSelf3P: SelfEqualsBoolProto { } @AddSelfEqualsMemberOperatorArbitrary struct HasEqualsSelf4P: SelfEqualsBoolProto { } func testHasEqualsSelf( x: HasEqualsSelf, y: HasEqualsSelf2, z: HasEqualsSelf3, w: HasEqualsSelf4, xP: HasEqualsSelfP, yP: HasEqualsSelf2P, zP: HasEqualsSelf3P, wP: HasEqualsSelf4P ) { #if TEST_DIAGNOSTICS // Global operator lookup doesn't find member operators introduced by macros. _ = (x == true) // expected-error{{referencing operator function '=='}} _ = (y == true) // expected-error{{referencing operator function '=='}} _ = (z == true) // expected-error{{referencing operator function '=='}} _ = (w == true) // expected-error{{referencing operator function '=='}} #endif // These should be found through the protocol. _ = (xP == true) _ = (yP == true) _ = (zP == true) _ = (wP == true) } // Macro whose implementation is both an expression and declaration macro. @freestanding(declaration) macro AsDeclMacro(_ value: T) = #externalMacro(module: "MacroDefinition", type: "ExprAndDeclMacro") @freestanding(expression) macro AsExprMacro(_ value: T) -> (T, String) = #externalMacro(module: "MacroDefinition", type: "ExprAndDeclMacro") func testExpressionAndDeclarationMacro() { #AsExprMacro(1 + 1) // expected-warning{{expression of type '(Int, String)' is unused}} struct Inner { #AsDeclMacro(1 + 1) } #AsDeclMacro(1 + 1) } // Expression macro implementation with declaration macro role @freestanding(declaration) macro stringifyAsDeclMacro(_ value: T) = #externalMacro(module: "MacroDefinition", type: "StringifyMacro") func testExpressionAsDeclarationMacro() { #if TEST_DIAGNOSTICS #stringifyAsDeclMacro(1+1) // expected-error@-1{{macro implementation type 'StringifyMacro' doesn't conform to required protocol 'DeclarationMacro' (from macro 'stringifyAsDeclMacro')}} #endif } // Deprecated macro @available(*, deprecated, message: "This macro is deprecated.") @freestanding(expression) macro deprecatedStringify(_ value: T) -> (T, String) = #externalMacro(module: "MacroDefinition", type: "StringifyMacro") @available(*, deprecated, message: "This macro is deprecated.") @freestanding(declaration) macro deprecatedStringifyAsDeclMacro(_ value: T) = #externalMacro(module: "MacroDefinition", type: "StringifyMacro") func testDeprecated() { // expected-warning@+1{{'deprecatedStringify' is deprecated: This macro is deprecated.}} _ = #deprecatedStringify(1 + 1) } #if TEST_DIAGNOSTICS struct DeprecatedStructWrapper { // expected-error@+2{{macro implementation type 'StringifyMacro' doesn't conform to required protocol 'DeclarationMacro' (from macro 'deprecatedStringifyAsDeclMacro')}} // expected-warning@+1{{'deprecatedStringifyAsDeclMacro' is deprecated: This macro is deprecated.}} #deprecatedStringifyAsDeclMacro(1 + 1) } #endif @freestanding(declaration, names: named(ComparableType)) macro DefineComparableType() = #externalMacro(module: "MacroDefinition", type: "DefineComparableTypeMacro") struct HasNestedType { #DefineComparableType } @attached(accessor) macro AddGetter() = #externalMacro(module: "MacroDefinition", type: "AddGetterMacro") // Make sure the mangling for the accessor macro doesn't kick local // discriminator assignment, which would miss the autoclosure. func testLocalAccessorMacroWithAutoclosure() { @AddGetter var x: Int = 2 func takesAutoclosure(_ x: @autoclosure () -> Int) {} takesAutoclosure(1) } @propertyWrapper struct SomePropertyWrapper { var wrappedValue: T init(wrappedValue: T) { self.wrappedValue = wrappedValue } init(projectedValue: Self) { self = projectedValue } var projectedValue: Self { self } } // Property wrappers on macros probably aren't all that useful, but make sure // we don't crash. @freestanding(expression) macro hasPropertyWrapperParam(@SomePropertyWrapper x: Int) = #externalMacro(module: "MacroDefinition", type: "GenericToVoidMacro") func testPropertyWrapperMacro() { #hasPropertyWrapperParam(x: 0) #hasPropertyWrapperParam($x: .init(wrappedValue: 0)) } #if swift(>=1.0) && TEST_DIAGNOSTICS // Test that macros can't be used in @abi struct ABIAttrWithFreestandingMacro1 { // expected-error@+1 {{cannot use pound literal in '@abi'}} @abi(#varValue) #varValue // expected-note@-1 {{in expansion of macro 'varValue' here}} /* expected-expansion@-3:3 {{ expected-error@2:6{{cannot use pound literal in '@abi'}} }} */ } struct ABIAttrWithFreestandingMacro2 { // expected-error@+1 {{cannot use pound literal in '@abi'}} @abi(#varValue) var value: Int { 0 } } struct ABIAttrWithFreestandingMacro3 { @abi(var value: Int) #varValue } #endif #if TEST_DIAGNOSTICS @freestanding(expression) macro missingMacro() = #externalMacro(module: "MacroDefinition", type: "BluhBlah") // FIXME: xpected-warning@-1 {{external macro implementation type 'MacroDefinition.BluhBlah' could not be found for macro 'missingMacro()'; 'MacroDefinition.BluhBlah' could not be found in library plugin '}} @freestanding(expression) macro notMacro() = #externalMacro(module: "MacroDefinition", type: "NotMacroStruct") // FIXME: xpected-warning@-1 {{macro implementation type 'MacroDefinition.NotMacroStruct' could not be found for macro 'notMacro()'; 'MacroDefinition.NotMacroStruct' is not a valid macro implementation type in library plugin '}} // Because this is a method in a local decl, it ends up getting delayed, so // we need to check it at the end of the file. // FIXME: We either need to switch to using CHECK-DAG, or ideally teach // the diagnostic verifier about macro expansion buffers. func invalidDeclarationMacro2() { struct LocalThing1 { func f() { #accidentalCodeItem // expected-note@-1 {{in expansion of macro 'accidentalCodeItem' here}} /* expected-expansion@-3:7 {{ expected-error@1:1{{expected macro expansion to produce a declaration}} }} */ } } } #endif // Make sure we compute captures for the introduced stored property here. struct HasStoredProperty { #AddStoredProperty(0) } class HasStoredPropertyClass { #AddStoredProperty(0) }