Skip to content

Commit 193c53b

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 (cherry picked from commit 35db928)
1 parent 4f6ec8e commit 193c53b

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
@@ -472,6 +472,35 @@ static std::string adjustMacroExpansionBufferName(StringRef name) {
472472
return result;
473473
}
474474

475+
Optional<unsigned>
476+
ExpandMacroExpansionExprRequest::evaluate(Evaluator &evaluator,
477+
MacroExpansionExpr *mee) const {
478+
ConcreteDeclRef macroRef = mee->getMacroRef();
479+
assert(macroRef && isa<MacroDecl>(macroRef.getDecl()) &&
480+
"MacroRef should be set before expansion");
481+
482+
auto *macro = cast<MacroDecl>(macroRef.getDecl());
483+
if (macro->getMacroRoles().contains(MacroRole::Expression)) {
484+
return expandMacroExpr(mee);
485+
}
486+
// For a non-expression macro, expand it as a declaration.
487+
else if (macro->getMacroRoles().contains(MacroRole::Declaration) ||
488+
macro->getMacroRoles().contains(MacroRole::CodeItem)) {
489+
if (!mee->getSubstituteDecl()) {
490+
auto *med = mee->createSubstituteDecl();
491+
TypeChecker::typeCheckDecl(med);
492+
}
493+
// Return the expanded buffer ID.
494+
return evaluateOrDefault(
495+
evaluator, ExpandMacroExpansionDeclRequest(mee->getSubstituteDecl()),
496+
None);
497+
}
498+
499+
// Other macro roles may also be encountered here, as they use
500+
// `MacroExpansionExpr` for resolution. In those cases, do not expand.
501+
return None;
502+
}
503+
475504
ArrayRef<unsigned> ExpandMemberAttributeMacros::evaluate(Evaluator &evaluator,
476505
Decl *decl) const {
477506
if (decl->isImplicit())
@@ -682,22 +711,24 @@ static std::string expandMacroDefinition(
682711
return expandedResult;
683712
}
684713

685-
Expr *swift::expandMacroExpr(
686-
DeclContext *dc, Expr *expr, ConcreteDeclRef macroRef, Type expandedType
687-
) {
714+
Optional<unsigned>
715+
swift::expandMacroExpr(MacroExpansionExpr *mee) {
716+
DeclContext *dc = mee->getDeclContext();
688717
ASTContext &ctx = dc->getASTContext();
689718
SourceManager &sourceMgr = ctx.SourceMgr;
719+
ConcreteDeclRef macroRef = mee->getMacroRef();
720+
Type expandedType = mee->getType();
690721

691722
auto moduleDecl = dc->getParentModule();
692-
auto sourceFile = moduleDecl->getSourceFileContainingLocation(expr->getLoc());
723+
auto sourceFile = moduleDecl->getSourceFileContainingLocation(mee->getLoc());
693724
if (!sourceFile)
694-
return nullptr;
725+
return None;
695726

696727
MacroDecl *macro = cast<MacroDecl>(macroRef.getDecl());
697728

698729
if (isFromExpansionOfMacro(sourceFile, macro, MacroRole::Expression)) {
699-
ctx.Diags.diagnose(expr->getLoc(), diag::macro_recursive, macro->getName());
700-
return nullptr;
730+
ctx.Diags.diagnose(mee->getLoc(), diag::macro_recursive, macro->getName());
731+
return None;
701732
}
702733

703734
// Evaluate the macro.
@@ -706,34 +737,33 @@ Expr *swift::expandMacroExpr(
706737
/// The discriminator used for the macro.
707738
LazyValue<std::string> discriminator([&]() -> std::string {
708739
#if SWIFT_SWIFT_PARSER
709-
if (auto expansionExpr = dyn_cast<MacroExpansionExpr>(expr)) {
710-
Mangle::ASTMangler mangler;
711-
return mangler.mangleMacroExpansion(expansionExpr);
712-
}
713-
#endif
740+
Mangle::ASTMangler mangler;
741+
return mangler.mangleMacroExpansion(mee);
742+
#else
714743
return "";
744+
#endif
715745
});
716746

717747
auto macroDef = macro->getDefinition();
718748
switch (macroDef.kind) {
719749
case MacroDefinition::Kind::Undefined:
720750
case MacroDefinition::Kind::Invalid:
721751
// Already diagnosed as an error elsewhere.
722-
return nullptr;
752+
return None;
723753

724754
case MacroDefinition::Kind::Builtin: {
725755
switch (macroDef.getBuiltinKind()) {
726756
case BuiltinMacroKind::ExternalMacro:
727757
ctx.Diags.diagnose(
728-
expr->getLoc(), diag::external_macro_outside_macro_definition);
729-
return nullptr;
758+
mee->getLoc(), diag::external_macro_outside_macro_definition);
759+
return None;
730760
}
731761
}
732762

733763
case MacroDefinition::Kind::Expanded: {
734764
// Expand the definition with the given arguments.
735765
auto result = expandMacroDefinition(
736-
macroDef.getExpanded(), macro, expr->getArgs());
766+
macroDef.getExpanded(), macro, mee->getArgs());
737767
evaluatedSource = llvm::MemoryBuffer::getMemBufferCopy(
738768
result, adjustMacroExpansionBufferName(*discriminator));
739769
break;
@@ -748,41 +778,41 @@ Expr *swift::expandMacroExpr(
748778
auto externalDef = evaluateOrDefault(ctx.evaluator, request, None);
749779
if (!externalDef) {
750780
ctx.Diags.diagnose(
751-
expr->getLoc(), diag::external_macro_not_found,
781+
mee->getLoc(), diag::external_macro_not_found,
752782
external.moduleName.str(),
753783
external.macroTypeName.str(),
754784
macro->getName()
755785
);
756786
macro->diagnose(diag::decl_declared_here, macro->getName());
757-
return nullptr;
787+
return None;
758788
}
759789

760790
#if SWIFT_SWIFT_PARSER
761-
PrettyStackTraceExpr debugStack(ctx, "expanding macro", expr);
791+
PrettyStackTraceExpr debugStack(ctx, "expanding macro", mee);
762792

763793
// Builtin macros are handled via ASTGen.
764794
auto astGenSourceFile = sourceFile->exportedSourceFile;
765795
if (!astGenSourceFile)
766-
return nullptr;
796+
return None;
767797

768798
const char *evaluatedSourceAddress;
769799
ptrdiff_t evaluatedSourceLength;
770800
swift_ASTGen_expandFreestandingMacro(
771801
&ctx.Diags, externalDef->opaqueHandle,
772802
static_cast<uint32_t>(externalDef->kind), discriminator->data(),
773803
discriminator->size(), astGenSourceFile,
774-
expr->getStartLoc().getOpaquePointerValue(), &evaluatedSourceAddress,
804+
mee->getStartLoc().getOpaquePointerValue(), &evaluatedSourceAddress,
775805
&evaluatedSourceLength);
776806
if (!evaluatedSourceAddress)
777-
return nullptr;
807+
return None;
778808
evaluatedSource = llvm::MemoryBuffer::getMemBufferCopy(
779809
{evaluatedSourceAddress, (size_t)evaluatedSourceLength},
780810
adjustMacroExpansionBufferName(*discriminator));
781811
free((void *)evaluatedSourceAddress);
782812
break;
783813
#else
784-
ctx.Diags.diagnose(expr->getLoc(), diag::macro_unsupported);
785-
return nullptr;
814+
ctx.Diags.diagnose(mee->getLoc(), diag::macro_unsupported);
815+
return None;
786816
#endif
787817
}
788818
}
@@ -803,9 +833,9 @@ Expr *swift::expandMacroExpr(
803833
GeneratedSourceInfo sourceInfo{
804834
GeneratedSourceInfo::ExpressionMacroExpansion,
805835
Lexer::getCharSourceRangeFromSourceRange(
806-
sourceMgr, expr->getSourceRange()),
836+
sourceMgr, mee->getSourceRange()),
807837
macroBufferRange,
808-
ASTNode(expr).getOpaqueValue(),
838+
ASTNode(mee).getOpaqueValue(),
809839
dc
810840
};
811841
sourceMgr.setGeneratedSourceInfo(macroBufferID, sourceInfo);
@@ -823,7 +853,7 @@ Expr *swift::expandMacroExpr(
823853
if (topLevelItems.size() != 1) {
824854
ctx.Diags.diagnose(
825855
macroBufferRange.getStart(), diag::expected_macro_expansion_expr);
826-
return nullptr;
856+
return macroBufferID;
827857
}
828858

829859
auto codeItem = topLevelItems.front();
@@ -833,7 +863,7 @@ Expr *swift::expandMacroExpr(
833863
if (!expandedExpr) {
834864
ctx.Diags.diagnose(
835865
macroBufferRange.getStart(), diag::expected_macro_expansion_expr);
836-
return nullptr;
866+
return macroBufferID;
837867
}
838868

839869
// Type-check the expanded expression.
@@ -850,12 +880,15 @@ Expr *swift::expandMacroExpr(
850880
Type realExpandedType = TypeChecker::typeCheckExpression(
851881
expandedExpr, dc, contextualType);
852882
if (!realExpandedType)
853-
return nullptr;
883+
return macroBufferID;
854884

855885
assert((expandedType->isEqual(realExpandedType) ||
856886
realExpandedType->hasError()) &&
857887
"Type checking changed the result type?");
858-
return expandedExpr;
888+
889+
mee->setRewritten(expandedExpr);
890+
891+
return macroBufferID;
859892
}
860893

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