Skip to content

Commit f6bdd26

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 d90134c commit f6bdd26

File tree

8 files changed

+103
-49
lines changed

8 files changed

+103
-49
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: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2937,13 +2937,13 @@ 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(),
2943+
nullptr, MacroRole::Expression, /*isImplicit=*/true, expandedType);
2944+
expansion->setMacroRef(macroRef);
2945+
(void)evaluateOrDefault(ctx.evaluator, ExpandMacroExpansionExprRequest {expansion}, None);
2946+
if (expansion->getRewritten()) {
29472947
cs.cacheExprTypes(expansion);
29482948
return expansion;
29492949
}
@@ -5386,12 +5386,12 @@ namespace {
53865386
auto macro = cast<MacroDecl>(overload.choice.getDecl());
53875387
ConcreteDeclRef macroRef = resolveConcreteDeclRef(macro, locator);
53885388
E->setMacroRef(macroRef);
5389+
E->setType(expandedType);
53895390

53905391
if (!cs.Options.contains(ConstraintSystemFlags::DisableMacroExpansions)) {
53915392
if (macro->getMacroRoles().contains(MacroRole::Expression)) {
5392-
if (auto newExpr = expandMacroExpr(dc, E, macroRef, expandedType)) {
5393-
E->setRewritten(newExpr);
5394-
}
5393+
(void)evaluateOrDefault(cs.getASTContext().evaluator,
5394+
ExpandMacroExpansionExprRequest {E}, None);
53955395
}
53965396
// For a non-expression macro, expand it as a declaration.
53975397
else if (macro->getMacroRoles().contains(MacroRole::Declaration) ||

lib/Sema/TypeCheckMacros.cpp

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

459+
Optional<unsigned>
460+
ExpandMacroExpansionExprRequest::evaluate(Evaluator &evaluator,
461+
MacroExpansionExpr *mee) const {
462+
assert(mee->getMacroRef() && "MacroRef should be set before expansion");
463+
return expandMacroExpr(mee);
464+
}
465+
459466
ArrayRef<unsigned> ExpandMemberAttributeMacros::evaluate(Evaluator &evaluator,
460467
Decl *decl) const {
461468
if (decl->isImplicit())
@@ -666,22 +673,24 @@ static std::string expandMacroDefinition(
666673
return expandedResult;
667674
}
668675

669-
Expr *swift::expandMacroExpr(
670-
DeclContext *dc, Expr *expr, ConcreteDeclRef macroRef, Type expandedType
671-
) {
676+
Optional<unsigned>
677+
swift::expandMacroExpr(MacroExpansionExpr *mee) {
678+
DeclContext *dc = mee->getDeclContext();
672679
ASTContext &ctx = dc->getASTContext();
673680
SourceManager &sourceMgr = ctx.SourceMgr;
681+
ConcreteDeclRef macroRef = mee->getMacroRef();
682+
Type expandedType = mee->getType();
674683

675684
auto moduleDecl = dc->getParentModule();
676-
auto sourceFile = moduleDecl->getSourceFileContainingLocation(expr->getLoc());
685+
auto sourceFile = moduleDecl->getSourceFileContainingLocation(mee->getLoc());
677686
if (!sourceFile)
678-
return nullptr;
687+
return None;
679688

680689
MacroDecl *macro = cast<MacroDecl>(macroRef.getDecl());
681690

682691
if (isFromExpansionOfMacro(sourceFile, macro, MacroRole::Expression)) {
683-
ctx.Diags.diagnose(expr->getLoc(), diag::macro_recursive, macro->getName());
684-
return nullptr;
692+
ctx.Diags.diagnose(mee->getLoc(), diag::macro_recursive, macro->getName());
693+
return None;
685694
}
686695

687696
// Evaluate the macro.
@@ -690,34 +699,33 @@ Expr *swift::expandMacroExpr(
690699
/// The discriminator used for the macro.
691700
LazyValue<std::string> discriminator([&]() -> std::string {
692701
#if SWIFT_SWIFT_PARSER
693-
if (auto expansionExpr = dyn_cast<MacroExpansionExpr>(expr)) {
694-
Mangle::ASTMangler mangler;
695-
return mangler.mangleMacroExpansion(expansionExpr);
696-
}
697-
#endif
702+
Mangle::ASTMangler mangler;
703+
return mangler.mangleMacroExpansion(mee);
704+
#else
698705
return "";
706+
#endif
699707
});
700708

701709
auto macroDef = macro->getDefinition();
702710
switch (macroDef.kind) {
703711
case MacroDefinition::Kind::Undefined:
704712
case MacroDefinition::Kind::Invalid:
705713
// Already diagnosed as an error elsewhere.
706-
return nullptr;
714+
return None;
707715

708716
case MacroDefinition::Kind::Builtin: {
709717
switch (macroDef.getBuiltinKind()) {
710718
case BuiltinMacroKind::ExternalMacro:
711719
ctx.Diags.diagnose(
712-
expr->getLoc(), diag::external_macro_outside_macro_definition);
713-
return nullptr;
720+
mee->getLoc(), diag::external_macro_outside_macro_definition);
721+
return None;
714722
}
715723
}
716724

717725
case MacroDefinition::Kind::Expanded: {
718726
// Expand the definition with the given arguments.
719727
auto result = expandMacroDefinition(
720-
macroDef.getExpanded(), macro, expr->getArgs());
728+
macroDef.getExpanded(), macro, mee->getArgs());
721729
evaluatedSource = llvm::MemoryBuffer::getMemBufferCopy(
722730
result, adjustMacroExpansionBufferName(*discriminator));
723731
break;
@@ -732,41 +740,41 @@ Expr *swift::expandMacroExpr(
732740
auto externalDef = evaluateOrDefault(ctx.evaluator, request, None);
733741
if (!externalDef) {
734742
ctx.Diags.diagnose(
735-
expr->getLoc(), diag::external_macro_not_found,
743+
mee->getLoc(), diag::external_macro_not_found,
736744
external.moduleName.str(),
737745
external.macroTypeName.str(),
738746
macro->getName()
739747
);
740748
macro->diagnose(diag::decl_declared_here, macro->getName());
741-
return nullptr;
749+
return None;
742750
}
743751

744752
#if SWIFT_SWIFT_PARSER
745-
PrettyStackTraceExpr debugStack(ctx, "expanding macro", expr);
753+
PrettyStackTraceExpr debugStack(ctx, "expanding macro", mee);
746754

747755
// Builtin macros are handled via ASTGen.
748756
auto astGenSourceFile = sourceFile->exportedSourceFile;
749757
if (!astGenSourceFile)
750-
return nullptr;
758+
return None;
751759

752760
const char *evaluatedSourceAddress;
753761
ptrdiff_t evaluatedSourceLength;
754762
swift_ASTGen_expandFreestandingMacro(
755763
&ctx.Diags, externalDef->opaqueHandle,
756764
static_cast<uint32_t>(externalDef->kind), discriminator->data(),
757765
discriminator->size(), astGenSourceFile,
758-
expr->getStartLoc().getOpaquePointerValue(), &evaluatedSourceAddress,
766+
mee->getStartLoc().getOpaquePointerValue(), &evaluatedSourceAddress,
759767
&evaluatedSourceLength);
760768
if (!evaluatedSourceAddress)
761-
return nullptr;
769+
return None;
762770
evaluatedSource = llvm::MemoryBuffer::getMemBufferCopy(
763771
{evaluatedSourceAddress, (size_t)evaluatedSourceLength},
764772
adjustMacroExpansionBufferName(*discriminator));
765773
free((void *)evaluatedSourceAddress);
766774
break;
767775
#else
768-
ctx.Diags.diagnose(expr->getLoc(), diag::macro_unsupported);
769-
return nullptr;
776+
ctx.Diags.diagnose(mee->getLoc(), diag::macro_unsupported);
777+
return None;
770778
#endif
771779
}
772780
}
@@ -787,9 +795,9 @@ Expr *swift::expandMacroExpr(
787795
GeneratedSourceInfo sourceInfo{
788796
GeneratedSourceInfo::ExpressionMacroExpansion,
789797
Lexer::getCharSourceRangeFromSourceRange(
790-
sourceMgr, expr->getSourceRange()),
798+
sourceMgr, mee->getSourceRange()),
791799
macroBufferRange,
792-
ASTNode(expr).getOpaqueValue(),
800+
ASTNode(mee).getOpaqueValue(),
793801
dc
794802
};
795803
sourceMgr.setGeneratedSourceInfo(macroBufferID, sourceInfo);
@@ -807,7 +815,7 @@ Expr *swift::expandMacroExpr(
807815
if (topLevelItems.size() != 1) {
808816
ctx.Diags.diagnose(
809817
macroBufferRange.getStart(), diag::expected_macro_expansion_expr);
810-
return nullptr;
818+
return macroBufferID;
811819
}
812820

813821
auto codeItem = topLevelItems.front();
@@ -817,7 +825,7 @@ Expr *swift::expandMacroExpr(
817825
if (!expandedExpr) {
818826
ctx.Diags.diagnose(
819827
macroBufferRange.getStart(), diag::expected_macro_expansion_expr);
820-
return nullptr;
828+
return macroBufferID;
821829
}
822830

823831
// Type-check the expanded expression.
@@ -834,12 +842,15 @@ Expr *swift::expandMacroExpr(
834842
Type realExpandedType = TypeChecker::typeCheckExpression(
835843
expandedExpr, dc, contextualType);
836844
if (!realExpandedType)
837-
return nullptr;
845+
return macroBufferID;
838846

839847
assert((expandedType->isEqual(realExpandedType) ||
840848
realExpandedType->hasError()) &&
841849
"Type checking changed the result type?");
842-
return expandedExpr;
850+
851+
mee->setRewritten(expandedExpr);
852+
853+
return macroBufferID;
843854
}
844855

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