Skip to content

Commit 35db928

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 35db928

File tree

8 files changed

+126
-61
lines changed

8 files changed

+126
-61
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: 11 additions & 22 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,23 +5387,11 @@ 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-
}
5404-
// Other macro roles may also be encountered here, as they use
5405-
// `MacroExpansionExpr` for resolution. In those cases, do not expand.
5393+
(void)evaluateOrDefault(cs.getASTContext().evaluator,
5394+
ExpandMacroExpansionExprRequest{E}, None);
54065395
}
54075396

54085397
cs.cacheExprTypes(E);

lib/Sema/TypeCheckMacros.cpp

Lines changed: 63 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -456,6 +456,35 @@ 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+
483+
// Other macro roles may also be encountered here, as they use
484+
// `MacroExpansionExpr` for resolution. In those cases, do not expand.
485+
return None;
486+
}
487+
459488
ArrayRef<unsigned> ExpandMemberAttributeMacros::evaluate(Evaluator &evaluator,
460489
Decl *decl) const {
461490
if (decl->isImplicit())
@@ -666,22 +695,24 @@ static std::string expandMacroDefinition(
666695
return expandedResult;
667696
}
668697

669-
Expr *swift::expandMacroExpr(
670-
DeclContext *dc, Expr *expr, ConcreteDeclRef macroRef, Type expandedType
671-
) {
698+
Optional<unsigned>
699+
swift::expandMacroExpr(MacroExpansionExpr *mee) {
700+
DeclContext *dc = mee->getDeclContext();
672701
ASTContext &ctx = dc->getASTContext();
673702
SourceManager &sourceMgr = ctx.SourceMgr;
703+
ConcreteDeclRef macroRef = mee->getMacroRef();
704+
Type expandedType = mee->getType();
674705

675706
auto moduleDecl = dc->getParentModule();
676-
auto sourceFile = moduleDecl->getSourceFileContainingLocation(expr->getLoc());
707+
auto sourceFile = moduleDecl->getSourceFileContainingLocation(mee->getLoc());
677708
if (!sourceFile)
678-
return nullptr;
709+
return None;
679710

680711
MacroDecl *macro = cast<MacroDecl>(macroRef.getDecl());
681712

682713
if (isFromExpansionOfMacro(sourceFile, macro, MacroRole::Expression)) {
683-
ctx.Diags.diagnose(expr->getLoc(), diag::macro_recursive, macro->getName());
684-
return nullptr;
714+
ctx.Diags.diagnose(mee->getLoc(), diag::macro_recursive, macro->getName());
715+
return None;
685716
}
686717

687718
// Evaluate the macro.
@@ -690,34 +721,33 @@ Expr *swift::expandMacroExpr(
690721
/// The discriminator used for the macro.
691722
LazyValue<std::string> discriminator([&]() -> std::string {
692723
#if SWIFT_SWIFT_PARSER
693-
if (auto expansionExpr = dyn_cast<MacroExpansionExpr>(expr)) {
694-
Mangle::ASTMangler mangler;
695-
return mangler.mangleMacroExpansion(expansionExpr);
696-
}
697-
#endif
724+
Mangle::ASTMangler mangler;
725+
return mangler.mangleMacroExpansion(mee);
726+
#else
698727
return "";
728+
#endif
699729
});
700730

701731
auto macroDef = macro->getDefinition();
702732
switch (macroDef.kind) {
703733
case MacroDefinition::Kind::Undefined:
704734
case MacroDefinition::Kind::Invalid:
705735
// Already diagnosed as an error elsewhere.
706-
return nullptr;
736+
return None;
707737

708738
case MacroDefinition::Kind::Builtin: {
709739
switch (macroDef.getBuiltinKind()) {
710740
case BuiltinMacroKind::ExternalMacro:
711741
ctx.Diags.diagnose(
712-
expr->getLoc(), diag::external_macro_outside_macro_definition);
713-
return nullptr;
742+
mee->getLoc(), diag::external_macro_outside_macro_definition);
743+
return None;
714744
}
715745
}
716746

717747
case MacroDefinition::Kind::Expanded: {
718748
// Expand the definition with the given arguments.
719749
auto result = expandMacroDefinition(
720-
macroDef.getExpanded(), macro, expr->getArgs());
750+
macroDef.getExpanded(), macro, mee->getArgs());
721751
evaluatedSource = llvm::MemoryBuffer::getMemBufferCopy(
722752
result, adjustMacroExpansionBufferName(*discriminator));
723753
break;
@@ -732,41 +762,41 @@ Expr *swift::expandMacroExpr(
732762
auto externalDef = evaluateOrDefault(ctx.evaluator, request, None);
733763
if (!externalDef) {
734764
ctx.Diags.diagnose(
735-
expr->getLoc(), diag::external_macro_not_found,
765+
mee->getLoc(), diag::external_macro_not_found,
736766
external.moduleName.str(),
737767
external.macroTypeName.str(),
738768
macro->getName()
739769
);
740770
macro->diagnose(diag::decl_declared_here, macro->getName());
741-
return nullptr;
771+
return None;
742772
}
743773

744774
#if SWIFT_SWIFT_PARSER
745-
PrettyStackTraceExpr debugStack(ctx, "expanding macro", expr);
775+
PrettyStackTraceExpr debugStack(ctx, "expanding macro", mee);
746776

747777
// Builtin macros are handled via ASTGen.
748778
auto astGenSourceFile = sourceFile->exportedSourceFile;
749779
if (!astGenSourceFile)
750-
return nullptr;
780+
return None;
751781

752782
const char *evaluatedSourceAddress;
753783
ptrdiff_t evaluatedSourceLength;
754784
swift_ASTGen_expandFreestandingMacro(
755785
&ctx.Diags, externalDef->opaqueHandle,
756786
static_cast<uint32_t>(externalDef->kind), discriminator->data(),
757787
discriminator->size(), astGenSourceFile,
758-
expr->getStartLoc().getOpaquePointerValue(), &evaluatedSourceAddress,
788+
mee->getStartLoc().getOpaquePointerValue(), &evaluatedSourceAddress,
759789
&evaluatedSourceLength);
760790
if (!evaluatedSourceAddress)
761-
return nullptr;
791+
return None;
762792
evaluatedSource = llvm::MemoryBuffer::getMemBufferCopy(
763793
{evaluatedSourceAddress, (size_t)evaluatedSourceLength},
764794
adjustMacroExpansionBufferName(*discriminator));
765795
free((void *)evaluatedSourceAddress);
766796
break;
767797
#else
768-
ctx.Diags.diagnose(expr->getLoc(), diag::macro_unsupported);
769-
return nullptr;
798+
ctx.Diags.diagnose(mee->getLoc(), diag::macro_unsupported);
799+
return None;
770800
#endif
771801
}
772802
}
@@ -787,9 +817,9 @@ Expr *swift::expandMacroExpr(
787817
GeneratedSourceInfo sourceInfo{
788818
GeneratedSourceInfo::ExpressionMacroExpansion,
789819
Lexer::getCharSourceRangeFromSourceRange(
790-
sourceMgr, expr->getSourceRange()),
820+
sourceMgr, mee->getSourceRange()),
791821
macroBufferRange,
792-
ASTNode(expr).getOpaqueValue(),
822+
ASTNode(mee).getOpaqueValue(),
793823
dc
794824
};
795825
sourceMgr.setGeneratedSourceInfo(macroBufferID, sourceInfo);
@@ -807,7 +837,7 @@ Expr *swift::expandMacroExpr(
807837
if (topLevelItems.size() != 1) {
808838
ctx.Diags.diagnose(
809839
macroBufferRange.getStart(), diag::expected_macro_expansion_expr);
810-
return nullptr;
840+
return macroBufferID;
811841
}
812842

813843
auto codeItem = topLevelItems.front();
@@ -817,7 +847,7 @@ Expr *swift::expandMacroExpr(
817847
if (!expandedExpr) {
818848
ctx.Diags.diagnose(
819849
macroBufferRange.getStart(), diag::expected_macro_expansion_expr);
820-
return nullptr;
850+
return macroBufferID;
821851
}
822852

823853
// Type-check the expanded expression.
@@ -834,12 +864,15 @@ Expr *swift::expandMacroExpr(
834864
Type realExpandedType = TypeChecker::typeCheckExpression(
835865
expandedExpr, dc, contextualType);
836866
if (!realExpandedType)
837-
return nullptr;
867+
return macroBufferID;
838868

839869
assert((expandedType->isEqual(realExpandedType) ||
840870
realExpandedType->hasError()) &&
841871
"Type checking changed the result type?");
842-
return expandedExpr;
872+
873+
mee->setRewritten(expandedExpr);
874+
875+
return macroBufferID;
843876
}
844877

845878
/// 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)