Skip to content

Commit 535aecb

Browse files
committed
[Macros] Check primary-file macro definitions more thoroughly.
Error if a macro is undefined, and warn if it refers to an external macro definition that cannot be found.
1 parent 32a918a commit 535aecb

File tree

7 files changed

+65
-3
lines changed

7 files changed

+65
-3
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6777,6 +6777,8 @@ ERROR(external_macro_not_found,none,
67776777
"external macro implementation type '%0.%1' could not be found for "
67786778
"macro %2; the type must be public and provided via "
67796779
"'-load-plugin-library'", (StringRef, StringRef, DeclName))
6780+
ERROR(macro_must_be_defined,none,
6781+
"macro %0 requires a definition", (DeclName))
67806782
NOTE(macro_note, none,
67816783
"%1 (in macro %0)", (DeclName, StringRef))
67826784
WARNING(macro_warning, none,

include/swift/AST/MacroDefinition.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ class MacroDefinition {
112112
return data.builtin;
113113
}
114114

115-
explicit operator bool() const { return kind != Kind::Invalid; }
115+
operator Kind() const { return kind; }
116116
};
117117

118118
}

lib/Sema/TypeCheckDeclPrimary.cpp

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2006,7 +2006,38 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
20062006
if (!MD->getMacroContexts())
20072007
MD->diagnose(diag::macro_without_context, MD->getName());
20082008

2009-
(void)MD->getDefinition();
2009+
// Check the macro definition.
2010+
switch (auto macroDef = MD->getDefinition()) {
2011+
case MacroDefinition::Kind::Undefined:
2012+
MD->diagnose(diag::macro_must_be_defined, MD->getName());
2013+
break;
2014+
2015+
case MacroDefinition::Kind::Invalid:
2016+
case MacroDefinition::Kind::Builtin:
2017+
// Nothing else to check here.
2018+
break;
2019+
2020+
case MacroDefinition::Kind::External: {
2021+
// Retrieve the external definition of the macro.
2022+
auto external = macroDef.getExternalMacro();
2023+
ExternalMacroDefinitionRequest request{
2024+
&Ctx, external.moduleName, external.macroTypeName
2025+
};
2026+
auto externalDef = evaluateOrDefault(
2027+
Ctx.evaluator, request, ExternalMacroDefinition()
2028+
);
2029+
if (!externalDef.opaqueHandle) {
2030+
MD->diagnose(
2031+
diag::external_macro_not_found,
2032+
external.moduleName.str(),
2033+
external.macroTypeName.str(),
2034+
MD->getName()
2035+
).limitBehavior(DiagnosticBehavior::Warning);
2036+
}
2037+
2038+
break;
2039+
}
2040+
}
20102041
}
20112042

20122043
void visitMacroExpansionDecl(MacroExpansionDecl *MED) {

lib/Sema/TypeCheckMacros.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -358,7 +358,7 @@ Expr *swift::expandMacroExpr(
358358
}
359359

360360
case MacroDefinition::Kind::External: {
361-
// Retrieve the extternal definition of the macro.
361+
// Retrieve the external definition of the macro.
362362
auto external = macroDef.getExternalMacro();
363363
ExternalMacroDefinitionRequest request{
364364
&ctx, external.moduleName, external.macroTypeName

test/Macros/macro_availability_macosx.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
struct X { }
66

77
@expression macro m1: X = #externalMacro(module: "A", type: "B") // expected-error{{'X' is only available in macOS 12.0 or newer}}
8+
// expected-warning@-1{{external macro implementation type 'A.B' could not be found for macro 'm1'}}
89
910
@available(macOS 12.0, *)
1011
@expression macro m2: X = #externalMacro(module: "A", type: "B")
12+
// expected-warning@-1{{external macro implementation type 'A.B' could not be found for macro 'm2'}}

test/Macros/macros_diagnostics.swift

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,12 @@
22

33
@expression macro stringify<T>(_ value: T) -> (T, String) = #externalMacro(module: "MacroDefinition", type: "StringifyMacro")
44
// expected-note@-1 2{{'stringify' declared here}}
5+
// expected-warning@-2{{external macro implementation type}}
56
@expression macro missingMacro1(_: Any) = MissingModule.MissingType // expected-note{{'missingMacro1' declared here}}
67
// expected-warning@-1{{external macro definitions are now written using #externalMacro}}{{43-68=#externalMacro(module: "MissingModule", type: "MissingType")}}
8+
// expected-warning@-2{{external macro implementation type}}
79
@expression macro missingMacro2(_: Any) = #externalMacro(module: "MissingModule", type: "MissingType")
10+
// expected-warning@-1{{external macro implementation type}}
811

912
protocol P { }
1013

@@ -16,36 +19,52 @@ internal struct X { } // expected-note{{type declared here}}
1619

1720
@expression public macro createAnX: X = #externalMacro(module: "BuiltinMacros", type: "Blah")
1821
// expected-error@-1{{macro cannot be declared public because its result type uses an internal type}}
22+
// expected-warning@-2{{external macro implementation type}}
1923

2024
@expression macro m1: Int = #externalMacro(module: "BuiltinMacros", type: "Blah")
25+
// expected-warning@-1{{external macro implementation type}}
2126
@expression macro m1: Float = #externalMacro(module: "BuiltinMacros", type: "Blah")
27+
// expected-warning@-1{{external macro implementation type}}
2228

2329
@expression macro m2: Int = #externalMacro(module: "BuiltinMacros", type: "Blah") // expected-note{{'m2' previously declared here}}
30+
// expected-warning@-1{{external macro implementation type}}
2431
@expression macro m2: Int = #externalMacro(module: "BuiltinMacros", type: "Blah") // expected-error{{invalid redeclaration of 'm2'}}
32+
// expected-warning@-1{{external macro implementation type}}
2533

2634
@expression macro m3(_: Int) -> Int = #externalMacro(module: "BuiltinMacros", type: "Blah")
35+
// expected-warning@-1{{external macro implementation type}}
2736
@expression macro m3(_: Int) -> Float = #externalMacro(module: "BuiltinMacros", type: "Blah")
37+
// expected-warning@-1{{external macro implementation type}}
2838

2939
@expression macro m4(_: Int) -> Int = #externalMacro(module: "BuiltinMacros", type: "Blah") // expected-note{{'m4' previously declared here}}
40+
// expected-warning@-1{{external macro implementation type}}
3041
@expression macro m4(_: Int) -> Int = #externalMacro(module: "BuiltinMacros", type: "Blah") // expected-error{{invalid redeclaration of 'm4'}}
42+
// expected-warning@-1{{external macro implementation type}}
3143

3244
struct ZZZ {
3345
macro m5: Int = #externalMacro(module: "BuiltinMacros", type: "Blah")
3446
// expected-error@-1{{macro 'm5' can only be declared at file scope}}
3547
// expected-error@-2{{macro 'm5' must declare its applicable contexts (e.g., '@expression')}}
48+
// expected-warning@-3{{external macro implementation type}}
3649
}
3750

3851
@expression macro multiArgMacro(_: Any, second: Any) = #externalMacro(module: "MissingModule", type: "MissingType")
3952
// expected-note@-1{{'multiArgMacro(_:second:)' declared here}}
53+
// expected-warning@-2{{external macro implementation type}}
4054

4155
@expression macro overloaded1(_ p: P) = #externalMacro(module: "MissingModule", type: "MissingType")
56+
// expected-warning@-1{{external macro implementation type}}
57+
4258
func overloaded1(_ p: Any) { }
4359

4460
@expression macro notOverloaded1(_ p: P) = #externalMacro(module: "MissingModule", type: "MissingType") // expected-note{{'notOverloaded1' previously declared here}}
61+
// expected-warning@-1{{external macro implementation type}}
4562
@expression macro notOverloaded1(_ p: P) = #externalMacro(module: "MissingModule", type: "MissingOtherType") // expected-error{{invalid redeclaration of 'notOverloaded1'}}
63+
// expected-warning@-1{{external macro implementation type}}
4664

4765
@expression macro intIdentity(value: Int, _: Float) -> Int = #externalMacro(module: "MissingModule", type: "MissingType")
4866
// expected-note@-1{{macro 'intIdentity(value:_:)' declared here}}
67+
// expected-warning@-2{{external macro implementation type}}
4968

5069
func testDiags(a: Int, b: Int) {
5170
// FIXME: Bad diagnostic.
@@ -80,3 +99,6 @@ func shadow(a: Int, b: Int, stringify: Int) {
8099
func testMissing() {
81100
#missingMacro1("hello") // expected-error{{external macro implementation type 'MissingModule.MissingType' could not be found for macro 'missingMacro1'; the type must be public and provided via '-load-plugin-library'}}
82101
}
102+
103+
@expression macro undefined() // expected-error{{macro 'undefined()' requires a definition}}
104+

test/Macros/parsing.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,15 @@ protocol P { }
33
protocol Q { associatedtype Assoc }
44

55
@expression macro m1: Int = #externalMacro(module: "A", type: "M1")
6+
// expected-warning@-1{{external macro implementation type 'A.M1' could not be found for macro 'm1'; the type must be public and provided via '-load-plugin-library'}}
67
@expression macro m2(_: Int) = #externalMacro(module: "A", type: "M2")
8+
// expected-warning@-1{{external macro implementation type 'A.M2' could not be found for macro 'm2'; the type must be public and provided via '-load-plugin-library'}}
79
@expression macro m3(a b: Int) -> Int = #externalMacro(module: "A", type: "M3")
10+
// expected-warning@-1{{external macro implementation type 'A.M3' could not be found for macro 'm3(a:)'; the type must be public and provided via '-load-plugin-library'}}
811
@expression macro m4<T: Q>: T = #externalMacro(module: "A", type: "M4") where T.Assoc: P
12+
// expected-warning@-1{{external macro implementation type 'A.M4' could not be found for macro 'm4'; the type must be public and provided via '-load-plugin-library'}}
913
@expression macro m5<T: P>(_: T) = #externalMacro(module: "A", type: "M4")
14+
// expected-warning@-1{{external macro implementation type 'A.M4' could not be found for macro 'm5'; the type must be public and provided via '-load-plugin-library'}}
1015

1116
@expression macro m6 = A // expected-error{{expected '(' for macro parameters or ':' for a value-like macro}}
1217
// expected-error@-1{{macro must itself be defined by a macro expansion such as '#externalMacro(...)'}}

0 commit comments

Comments
 (0)