Skip to content

Commit 8fc94b8

Browse files
authored
Merge pull request #62532 from DougGregor/missing-macro-only-on-expansion
2 parents 62e00fd + 54625a3 commit 8fc94b8

File tree

6 files changed

+88
-46
lines changed

6 files changed

+88
-46
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6746,7 +6746,7 @@ ERROR(macro_undefined,PointsToFirstBadToken,
67466746
"macro %0 is undefined; use `-load-plugin-library` to specify dynamic "
67476747
"libraries that contain this macro", (Identifier))
67486748
ERROR(external_macro_not_found,none,
6749-
"external implementation struct '%0.%1' could not be found in for "
6749+
"external macro implementation type '%0.%1' could not be found for "
67506750
"macro %2; the type must be public and provided via "
67516751
"'-load-plugin-library'", (StringRef, StringRef, DeclName))
67526752
NOTE(macro_note, none,

include/swift/AST/MacroDefinition.h

Lines changed: 33 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -23,21 +23,33 @@
2323
namespace swift {
2424

2525
/// Provides the definition of a macro.
26-
struct MacroDefinition {
27-
/// The kind of macro, which determines how it can be used in source code.
26+
class MacroDefinition {
27+
public:
28+
/// The kind of macro, which determines how it can be used in source code.
2829
enum Kind: uint8_t {
29-
/// An expression macro.
30+
/// An expression macro.
3031
Expression,
3132
};
3233

34+
/// Describes a missing macro definition.
35+
struct MissingDefinition {
36+
Identifier externalModuleName;
37+
Identifier externalMacroTypeName;
38+
};
39+
3340
/// Describes how the macro is implemented.
3441
enum class ImplementationKind: uint8_t {
42+
/// The macro has no definition.
43+
Undefined,
44+
45+
/// The macro has a definition, but it could not be found.
46+
Missing,
47+
3548
/// The macro is in the same process as the compiler, whether built-in or
3649
/// loaded via a compiler plugin.
3750
InProcess,
3851
};
3952

40-
public:
4153
Kind kind;
4254
ImplementationKind implKind;
4355

@@ -48,25 +60,32 @@ struct MacroDefinition {
4860
: kind(kind), implKind(implKind), opaqueHandle(opaqueHandle) { }
4961

5062
public:
51-
static MacroDefinition forInvalid() {
63+
static MacroDefinition forUndefined() {
5264
return MacroDefinition{
53-
Kind::Expression, ImplementationKind::InProcess, nullptr
65+
Kind::Expression, ImplementationKind::Undefined, nullptr
5466
};
5567
}
5668

69+
static MacroDefinition forMissing(
70+
ASTContext &ctx,
71+
Identifier externalModuleName,
72+
Identifier externalMacroTypeName
73+
);
74+
5775
static MacroDefinition forInProcess(Kind kind, void *opaqueHandle) {
5876
return MacroDefinition{kind, ImplementationKind::InProcess, opaqueHandle};
5977
}
6078

61-
bool isInvalid() const { return opaqueHandle == nullptr; }
62-
63-
explicit operator bool() const { return !isInvalid(); }
79+
/// Return the opaque handle for an in-process macro definition.
80+
void *getInProcessOpaqueHandle() const {
81+
assert(implKind == ImplementationKind::InProcess);
82+
return opaqueHandle;
83+
}
6484

65-
void *getAsInProcess() const {
66-
switch (implKind) {
67-
case ImplementationKind::InProcess:
68-
return opaqueHandle;
69-
}
85+
/// Return more information about a missing macro definition.
86+
MissingDefinition *getMissingDefinition() const {
87+
assert(implKind == ImplementationKind::Missing);
88+
return static_cast<MissingDefinition *>(opaqueHandle);
7089
}
7190
};
7291

include/swift/AST/TypeCheckRequests.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ class DefaultArgumentType;
4848
class ClosureExpr;
4949
class GenericParamList;
5050
class LabeledStmt;
51-
struct MacroDefinition;
51+
class MacroDefinition;
5252
class PrecedenceGroupDecl;
5353
class PropertyWrapperInitializerInfo;
5454
struct PropertyWrapperLValueness;

lib/AST/Decl.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include "swift/AST/GenericSignature.h"
3333
#include "swift/AST/Initializer.h"
3434
#include "swift/AST/LazyResolver.h"
35+
#include "swift/AST/MacroDefinition.h"
3536
#include "swift/AST/Module.h"
3637
#include "swift/AST/NameLookup.h"
3738
#include "swift/AST/NameLookupRequests.h"
@@ -9682,3 +9683,15 @@ SourceRange MacroExpansionDecl::getSourceRange() const {
96829683

96839684
return SourceRange(PoundLoc, endLoc);
96849685
}
9686+
9687+
MacroDefinition MacroDefinition::forMissing(
9688+
ASTContext &ctx, Identifier externalModuleName,
9689+
Identifier externalMacroTypeName
9690+
) {
9691+
auto def = ctx.AllocateObjectCopy(
9692+
MissingDefinition{externalModuleName, externalMacroTypeName}
9693+
);
9694+
return MacroDefinition{
9695+
Kind::Expression, ImplementationKind::Missing, def
9696+
};
9697+
}

lib/Sema/TypeCheckMacros.cpp

Lines changed: 34 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -119,12 +119,8 @@ MacroDefinition MacroDefinitionRequest::evaluate(
119119
}
120120
#endif
121121

122-
ctx.Diags.diagnose(
123-
macro, diag::external_macro_not_found, macro->externalModuleName.str(),
124-
macro->externalMacroTypeName.str(), macro->getName());
125-
// FIXME: Can we give more actionable advice?
126-
127-
return MacroDefinition::forInvalid();
122+
return MacroDefinition::forMissing(
123+
ctx, macro->externalModuleName, macro->externalMacroTypeName);
128124
}
129125

130126
#if SWIFT_SWIFT_PARSER
@@ -150,35 +146,43 @@ Expr *swift::expandMacroExpr(
150146

151147
auto macroDef = evaluateOrDefault(
152148
ctx.evaluator, MacroDefinitionRequest{macro},
153-
MacroDefinition::forInvalid());
154-
if (!macroDef) {
149+
MacroDefinition::forUndefined());
150+
switch (macroDef.implKind) {
151+
case MacroDefinition::ImplementationKind::Undefined:
152+
// Already diagnosed as an error elsewhere.
153+
return nullptr;
154+
155+
case MacroDefinition::ImplementationKind::Missing: {
156+
auto missingInfo = macroDef.getMissingDefinition();
157+
ctx.Diags.diagnose(
158+
expr->getLoc(), diag::external_macro_not_found,
159+
missingInfo->externalModuleName.str(),
160+
missingInfo->externalMacroTypeName.str(), macro->getName());
161+
macro->diagnose(diag::decl_declared_here, macro->getName());
155162
return nullptr;
156163
}
157164

158-
{
165+
case MacroDefinition::ImplementationKind::InProcess: {
159166
PrettyStackTraceExpr debugStack(ctx, "expanding macro", expr);
160167

161-
switch (macroDef.implKind) {
162-
case MacroDefinition::ImplementationKind::InProcess: {
163-
// Builtin macros are handled via ASTGen.
164-
auto astGenSourceFile = sourceFile->exportedSourceFile;
165-
if (!astGenSourceFile)
166-
return nullptr;
167-
168-
const char *evaluatedSourceAddress;
169-
ptrdiff_t evaluatedSourceLength;
170-
swift_ASTGen_evaluateMacro(
171-
&ctx.Diags,
172-
macroDef.getAsInProcess(),
173-
astGenSourceFile, expr->getStartLoc().getOpaquePointerValue(),
174-
&evaluatedSourceAddress, &evaluatedSourceLength);
175-
if (!evaluatedSourceAddress)
176-
return nullptr;
177-
evaluatedSource = NullTerminatedStringRef(evaluatedSourceAddress,
178-
(size_t)evaluatedSourceLength);
179-
break;
180-
}
181-
}
168+
// Builtin macros are handled via ASTGen.
169+
auto astGenSourceFile = sourceFile->exportedSourceFile;
170+
if (!astGenSourceFile)
171+
return nullptr;
172+
173+
const char *evaluatedSourceAddress;
174+
ptrdiff_t evaluatedSourceLength;
175+
swift_ASTGen_evaluateMacro(
176+
&ctx.Diags,
177+
macroDef.getInProcessOpaqueHandle(),
178+
astGenSourceFile, expr->getStartLoc().getOpaquePointerValue(),
179+
&evaluatedSourceAddress, &evaluatedSourceLength);
180+
if (!evaluatedSourceAddress)
181+
return nullptr;
182+
evaluatedSource = NullTerminatedStringRef(evaluatedSourceAddress,
183+
(size_t)evaluatedSourceLength);
184+
break;
185+
}
182186
}
183187

184188
// Figure out a reasonable name for the macro expansion buffer.

test/Macros/macros_diagnostics.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
// REQUIRES: OS=macosx
33

44
macro stringify<T>(_ value: T) -> (T, String) = _SwiftSyntaxMacros.StringifyMacro
5+
macro missingMacro1(_: Any) = MissingModule.MissingType // expected-note{{'missingMacro1' declared here}}
6+
macro missingMacro2(_: Any) = MissingModule.MissingType
57

68
protocol P { }
79

@@ -38,3 +40,7 @@ func test(a: Int, b: Int) {
3840
func shadow(a: Int, b: Int, stringify: Int) {
3941
_ = #stringify(a + b)
4042
}
43+
44+
func testMissing() {
45+
#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'}}
46+
}

0 commit comments

Comments
 (0)