Skip to content

Commit ec07e83

Browse files
committed
[Macros] Requestify MacroExpansionExpr expansion
The request returns the expanded buffer ID even if it failed to typecheck the expanded buffer. This makes refactoring 'Expand Macro' work regardless of the typechecking results. rdar://108530760
1 parent 2c08dc2 commit ec07e83

File tree

8 files changed

+124
-59
lines changed

8 files changed

+124
-59
lines changed

include/swift/AST/TypeCheckRequests.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3930,6 +3930,26 @@ class ExpandMacroExpansionDeclRequest
39303930
void noteCycleStep(DiagnosticEngine &diags) const;
39313931
};
39323932

3933+
/// Expand a 'MacroExpansionExpr',
3934+
class ExpandMacroExpansionExprRequest
3935+
: public SimpleRequest<ExpandMacroExpansionExprRequest,
3936+
Optional<unsigned>(MacroExpansionExpr *),
3937+
RequestFlags::Cached> {
3938+
public:
3939+
using SimpleRequest::SimpleRequest;
3940+
3941+
private:
3942+
friend SimpleRequest;
3943+
3944+
Optional<unsigned>
3945+
evaluate(Evaluator &evaluator, MacroExpansionExpr *mee) const;
3946+
3947+
public:
3948+
bool isCached() const { return true; }
3949+
void diagnoseCycle(DiagnosticEngine &diags) const;
3950+
void noteCycleStep(DiagnosticEngine &diags) const;
3951+
};
3952+
39333953
/// Expand all accessor macros attached to the given declaration.
39343954
///
39353955
/// Produces the set of macro expansion buffer IDs.

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -439,6 +439,9 @@ SWIFT_REQUEST(TypeChecker, ExternalMacroDefinitionRequest,
439439
SWIFT_REQUEST(TypeChecker, ExpandMacroExpansionDeclRequest,
440440
ArrayRef<Decl *>(MacroExpansionDecl *),
441441
Cached, NoLocationInfo)
442+
SWIFT_REQUEST(TypeChecker, ExpandMacroExpansionExprRequest,
443+
ArrayRef<Decl *>(MacroExpansionExpr *),
444+
Cached, NoLocationInfo)
442445
SWIFT_REQUEST(TypeChecker, ExpandMemberAttributeMacros,
443446
ArrayRef<unsigned>(Decl *),
444447
Cached, NoLocationInfo)

lib/AST/TypeCheckRequests.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1833,6 +1833,22 @@ void ExpandMacroExpansionDeclRequest::noteCycleStep(DiagnosticEngine &diags) con
18331833
decl->getMacroName().getFullName());
18341834
}
18351835

1836+
void ExpandMacroExpansionExprRequest::diagnoseCycle(DiagnosticEngine &diags) const {
1837+
auto expr = std::get<0>(getStorage());
1838+
diags.diagnose(expr->getStartLoc(),
1839+
diag::macro_expand_circular_reference,
1840+
"freestanding",
1841+
expr->getMacroName().getFullName());
1842+
}
1843+
1844+
void ExpandMacroExpansionExprRequest::noteCycleStep(DiagnosticEngine &diags) const {
1845+
auto expr = std::get<0>(getStorage());
1846+
diags.diagnose(expr->getStartLoc(),
1847+
diag::macro_expand_circular_reference_through,
1848+
"freestanding",
1849+
expr->getMacroName().getFullName());
1850+
}
1851+
18361852
void ExpandAccessorMacros::diagnoseCycle(DiagnosticEngine &diags) const {
18371853
auto decl = std::get<0>(getStorage());
18381854
diags.diagnose(decl->getLoc(),

lib/Refactoring/Refactoring.cpp

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8622,11 +8622,9 @@ bool RefactoringActionAddAsyncWrapper::performChange() {
86228622
/// expression.
86238623
static Optional<unsigned> getMacroExpansionBuffer(
86248624
SourceManager &sourceMgr, MacroExpansionExpr *expansion) {
8625-
if (auto rewritten = expansion->getRewritten()) {
8626-
return sourceMgr.findBufferContainingLoc(rewritten->getStartLoc());
8627-
}
8628-
8629-
return None;
8625+
return evaluateOrDefault(
8626+
expansion->getDeclContext()->getASTContext().evaluator,
8627+
ExpandMacroExpansionExprRequest{expansion}, {});
86308628
}
86318629

86328630
/// Retrieve the macro expansion buffer for the given macro expansion

lib/Sema/CSApply.cpp

Lines changed: 12 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2937,13 +2937,14 @@ namespace {
29372937

29382938
auto macro = cast<MacroDecl>(overload.choice.getDecl());
29392939
ConcreteDeclRef macroRef = resolveConcreteDeclRef(macro, locator);
2940-
if (auto newExpr = expandMacroExpr(dc, expr, macroRef, expandedType)) {
2941-
auto expansion = new (ctx) MacroExpansionExpr(
2942-
dc, expr->getStartLoc(), DeclNameRef(macro->getName()),
2943-
DeclNameLoc(expr->getLoc()), SourceLoc(), { }, SourceLoc(),
2944-
nullptr, MacroRole::Expression, /*isImplicit=*/true, expandedType);
2945-
expansion->setMacroRef(macroRef);
2946-
expansion->setRewritten(newExpr);
2940+
auto expansion = new (ctx) MacroExpansionExpr(
2941+
dc, expr->getStartLoc(), DeclNameRef(macro->getName()),
2942+
DeclNameLoc(expr->getLoc()), SourceLoc(), {}, SourceLoc(), nullptr,
2943+
MacroRole::Expression, /*isImplicit=*/true, expandedType);
2944+
expansion->setMacroRef(macroRef);
2945+
(void)evaluateOrDefault(
2946+
ctx.evaluator, ExpandMacroExpansionExprRequest{expansion}, None);
2947+
if (expansion->getRewritten()) {
29472948
cs.cacheExprTypes(expansion);
29482949
return expansion;
29492950
}
@@ -5386,21 +5387,12 @@ namespace {
53865387
auto macro = cast<MacroDecl>(overload.choice.getDecl());
53875388
ConcreteDeclRef macroRef = resolveConcreteDeclRef(macro, locator);
53885389
E->setMacroRef(macroRef);
5390+
E->setType(expandedType);
53895391

53905392
if (!cs.Options.contains(ConstraintSystemFlags::DisableMacroExpansions)) {
5391-
if (macro->getMacroRoles().contains(MacroRole::Expression)) {
5392-
if (auto newExpr = expandMacroExpr(dc, E, macroRef, expandedType)) {
5393-
E->setRewritten(newExpr);
5394-
}
5395-
}
5396-
// For a non-expression macro, expand it as a declaration.
5397-
else if (macro->getMacroRoles().contains(MacroRole::Declaration) ||
5398-
macro->getMacroRoles().contains(MacroRole::CodeItem)) {
5399-
if (!E->getSubstituteDecl()) {
5400-
auto *med = E->createSubstituteDecl();
5401-
TypeChecker::typeCheckDecl(med);
5402-
}
5403-
}
5393+
(void)evaluateOrDefault(cs.getASTContext().evaluator,
5394+
ExpandMacroExpansionExprRequest{E}, None);
5395+
54045396
// Other macro roles may also be encountered here, as they use
54055397
// `MacroExpansionExpr` for resolution. In those cases, do not expand.
54065398
}

lib/Sema/TypeCheckMacros.cpp

Lines changed: 60 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -456,6 +456,32 @@ static std::string adjustMacroExpansionBufferName(StringRef name) {
456456
return result;
457457
}
458458

459+
Optional<unsigned>
460+
ExpandMacroExpansionExprRequest::evaluate(Evaluator &evaluator,
461+
MacroExpansionExpr *mee) const {
462+
ConcreteDeclRef macroRef = mee->getMacroRef();
463+
assert(macroRef && isa<MacroDecl>(macroRef.getDecl()) &&
464+
"MacroRef should be set before expansion");
465+
466+
auto *macro = cast<MacroDecl>(macroRef.getDecl());
467+
if (macro->getMacroRoles().contains(MacroRole::Expression)) {
468+
return expandMacroExpr(mee);
469+
}
470+
// For a non-expression macro, expand it as a declaration.
471+
else if (macro->getMacroRoles().contains(MacroRole::Declaration) ||
472+
macro->getMacroRoles().contains(MacroRole::CodeItem)) {
473+
if (!mee->getSubstituteDecl()) {
474+
auto *med = mee->createSubstituteDecl();
475+
TypeChecker::typeCheckDecl(med);
476+
}
477+
// Return the expanded buffer ID.
478+
return evaluateOrDefault(
479+
evaluator, ExpandMacroExpansionDeclRequest(mee->getSubstituteDecl()),
480+
None);
481+
}
482+
return None;
483+
}
484+
459485
ArrayRef<unsigned> ExpandMemberAttributeMacros::evaluate(Evaluator &evaluator,
460486
Decl *decl) const {
461487
if (decl->isImplicit())
@@ -666,22 +692,24 @@ static std::string expandMacroDefinition(
666692
return expandedResult;
667693
}
668694

669-
Expr *swift::expandMacroExpr(
670-
DeclContext *dc, Expr *expr, ConcreteDeclRef macroRef, Type expandedType
671-
) {
695+
Optional<unsigned>
696+
swift::expandMacroExpr(MacroExpansionExpr *mee) {
697+
DeclContext *dc = mee->getDeclContext();
672698
ASTContext &ctx = dc->getASTContext();
673699
SourceManager &sourceMgr = ctx.SourceMgr;
700+
ConcreteDeclRef macroRef = mee->getMacroRef();
701+
Type expandedType = mee->getType();
674702

675703
auto moduleDecl = dc->getParentModule();
676-
auto sourceFile = moduleDecl->getSourceFileContainingLocation(expr->getLoc());
704+
auto sourceFile = moduleDecl->getSourceFileContainingLocation(mee->getLoc());
677705
if (!sourceFile)
678-
return nullptr;
706+
return None;
679707

680708
MacroDecl *macro = cast<MacroDecl>(macroRef.getDecl());
681709

682710
if (isFromExpansionOfMacro(sourceFile, macro, MacroRole::Expression)) {
683-
ctx.Diags.diagnose(expr->getLoc(), diag::macro_recursive, macro->getName());
684-
return nullptr;
711+
ctx.Diags.diagnose(mee->getLoc(), diag::macro_recursive, macro->getName());
712+
return None;
685713
}
686714

687715
// Evaluate the macro.
@@ -690,34 +718,33 @@ Expr *swift::expandMacroExpr(
690718
/// The discriminator used for the macro.
691719
LazyValue<std::string> discriminator([&]() -> std::string {
692720
#if SWIFT_SWIFT_PARSER
693-
if (auto expansionExpr = dyn_cast<MacroExpansionExpr>(expr)) {
694-
Mangle::ASTMangler mangler;
695-
return mangler.mangleMacroExpansion(expansionExpr);
696-
}
697-
#endif
721+
Mangle::ASTMangler mangler;
722+
return mangler.mangleMacroExpansion(mee);
723+
#else
698724
return "";
725+
#endif
699726
});
700727

701728
auto macroDef = macro->getDefinition();
702729
switch (macroDef.kind) {
703730
case MacroDefinition::Kind::Undefined:
704731
case MacroDefinition::Kind::Invalid:
705732
// Already diagnosed as an error elsewhere.
706-
return nullptr;
733+
return None;
707734

708735
case MacroDefinition::Kind::Builtin: {
709736
switch (macroDef.getBuiltinKind()) {
710737
case BuiltinMacroKind::ExternalMacro:
711738
ctx.Diags.diagnose(
712-
expr->getLoc(), diag::external_macro_outside_macro_definition);
713-
return nullptr;
739+
mee->getLoc(), diag::external_macro_outside_macro_definition);
740+
return None;
714741
}
715742
}
716743

717744
case MacroDefinition::Kind::Expanded: {
718745
// Expand the definition with the given arguments.
719746
auto result = expandMacroDefinition(
720-
macroDef.getExpanded(), macro, expr->getArgs());
747+
macroDef.getExpanded(), macro, mee->getArgs());
721748
evaluatedSource = llvm::MemoryBuffer::getMemBufferCopy(
722749
result, adjustMacroExpansionBufferName(*discriminator));
723750
break;
@@ -732,41 +759,41 @@ Expr *swift::expandMacroExpr(
732759
auto externalDef = evaluateOrDefault(ctx.evaluator, request, None);
733760
if (!externalDef) {
734761
ctx.Diags.diagnose(
735-
expr->getLoc(), diag::external_macro_not_found,
762+
mee->getLoc(), diag::external_macro_not_found,
736763
external.moduleName.str(),
737764
external.macroTypeName.str(),
738765
macro->getName()
739766
);
740767
macro->diagnose(diag::decl_declared_here, macro->getName());
741-
return nullptr;
768+
return None;
742769
}
743770

744771
#if SWIFT_SWIFT_PARSER
745-
PrettyStackTraceExpr debugStack(ctx, "expanding macro", expr);
772+
PrettyStackTraceExpr debugStack(ctx, "expanding macro", mee);
746773

747774
// Builtin macros are handled via ASTGen.
748775
auto astGenSourceFile = sourceFile->exportedSourceFile;
749776
if (!astGenSourceFile)
750-
return nullptr;
777+
return None;
751778

752779
const char *evaluatedSourceAddress;
753780
ptrdiff_t evaluatedSourceLength;
754781
swift_ASTGen_expandFreestandingMacro(
755782
&ctx.Diags, externalDef->opaqueHandle,
756783
static_cast<uint32_t>(externalDef->kind), discriminator->data(),
757784
discriminator->size(), astGenSourceFile,
758-
expr->getStartLoc().getOpaquePointerValue(), &evaluatedSourceAddress,
785+
mee->getStartLoc().getOpaquePointerValue(), &evaluatedSourceAddress,
759786
&evaluatedSourceLength);
760787
if (!evaluatedSourceAddress)
761-
return nullptr;
788+
return None;
762789
evaluatedSource = llvm::MemoryBuffer::getMemBufferCopy(
763790
{evaluatedSourceAddress, (size_t)evaluatedSourceLength},
764791
adjustMacroExpansionBufferName(*discriminator));
765792
free((void *)evaluatedSourceAddress);
766793
break;
767794
#else
768-
ctx.Diags.diagnose(expr->getLoc(), diag::macro_unsupported);
769-
return nullptr;
795+
ctx.Diags.diagnose(mee->getLoc(), diag::macro_unsupported);
796+
return None;
770797
#endif
771798
}
772799
}
@@ -787,9 +814,9 @@ Expr *swift::expandMacroExpr(
787814
GeneratedSourceInfo sourceInfo{
788815
GeneratedSourceInfo::ExpressionMacroExpansion,
789816
Lexer::getCharSourceRangeFromSourceRange(
790-
sourceMgr, expr->getSourceRange()),
817+
sourceMgr, mee->getSourceRange()),
791818
macroBufferRange,
792-
ASTNode(expr).getOpaqueValue(),
819+
ASTNode(mee).getOpaqueValue(),
793820
dc
794821
};
795822
sourceMgr.setGeneratedSourceInfo(macroBufferID, sourceInfo);
@@ -807,7 +834,7 @@ Expr *swift::expandMacroExpr(
807834
if (topLevelItems.size() != 1) {
808835
ctx.Diags.diagnose(
809836
macroBufferRange.getStart(), diag::expected_macro_expansion_expr);
810-
return nullptr;
837+
return macroBufferID;
811838
}
812839

813840
auto codeItem = topLevelItems.front();
@@ -817,7 +844,7 @@ Expr *swift::expandMacroExpr(
817844
if (!expandedExpr) {
818845
ctx.Diags.diagnose(
819846
macroBufferRange.getStart(), diag::expected_macro_expansion_expr);
820-
return nullptr;
847+
return macroBufferID;
821848
}
822849

823850
// Type-check the expanded expression.
@@ -834,12 +861,15 @@ Expr *swift::expandMacroExpr(
834861
Type realExpandedType = TypeChecker::typeCheckExpression(
835862
expandedExpr, dc, contextualType);
836863
if (!realExpandedType)
837-
return nullptr;
864+
return macroBufferID;
838865

839866
assert((expandedType->isEqual(realExpandedType) ||
840867
realExpandedType->hasError()) &&
841868
"Type checking changed the result type?");
842-
return expandedExpr;
869+
870+
mee->setRewritten(expandedExpr);
871+
872+
return macroBufferID;
843873
}
844874

845875
/// Expands the given macro expansion declaration.

lib/Sema/TypeCheckMacros.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,16 +29,15 @@ namespace swift {
2929
class CustomAttr;
3030
class Expr;
3131
class MacroDecl;
32+
class MacroExpansionExpr;
3233
class MacroExpansionDecl;
3334
class TypeRepr;
3435

3536
/// Expands the given macro expression and type-check the result with
3637
/// the given expanded type.
3738
///
38-
/// \returns the type-checked replacement expression, or NULL if the
39-
// macro could not be expanded.
40-
Expr *expandMacroExpr(
41-
DeclContext *dc, Expr *expr, ConcreteDeclRef macroRef, Type expandedType);
39+
/// \returns Expansion buffer ID if expansion succeeded, \p None if failed.
40+
Optional<unsigned> expandMacroExpr(MacroExpansionExpr *mee);
4241

4342
/// Expands the given macro expansion declaration.
4443
///

test/SourceKit/Macros/macro_basic.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,10 @@ macro anonymousTypes(_: () -> String) = #externalMacro(module: "MacroDefinition"
5656

5757
#anonymousTypes { "hello" }
5858

59+
// This should fails to typecheck because `#assert("foo")` is expanded to `assert("foo")`, but `assert(_:)` expects 'Bool' argument
60+
@freestanding(expression) macro assert(_: String) = #externalMacro(module: "MacroDefinition", type: "AssertMacro")
61+
#assert("foobar")
62+
5963
// REQUIRES: swift_swift_parser, executable_test, shell
6064

6165
// RUN: %empty-directory(%t)
@@ -265,3 +269,6 @@ macro anonymousTypes(_: () -> String) = #externalMacro(module: "MacroDefinition"
265269
// RUN: %sourcekitd-test -req=format -line=23 -length=1 %s | %FileCheck -check-prefix=FORMATTED %s
266270
// FORMATTED: " var x: Int"
267271

272+
//##-- Expansion on "fails to typecheck" macro expression
273+
// RUN: %sourcekitd-test -req=refactoring.expand.macro -pos=61:2 %s -- ${COMPILER_ARGS[@]} | %FileCheck -check-prefix=ERRONEOUS_EXPAND %s
274+
// ERRONEOUS_EXPAND: 61:1-61:18 (@__swiftmacro_9MacroUser6assertfMf_.swift) "assert("foobar")"

0 commit comments

Comments
 (0)