Skip to content

Commit ad7b1d9

Browse files
authored
Merge pull request #65480 from rintaro/5.9-macros-expandexpr-request-rdar108530760
[5.9][Macros] Requestify MacroExpansionExpr expansion
2 parents e5d9ae2 + c0533a7 commit ad7b1d9

File tree

11 files changed

+251
-144
lines changed

11 files changed

+251
-144
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)

include/swift/Basic/Lazy.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,41 @@
1414
#define SWIFT_BASIC_LAZY_H
1515

1616
#include <memory>
17+
#include <functional>
1718

1819
#include "swift/Basic/Malloc.h"
1920
#include "swift/Basic/type_traits.h"
2021
#include "swift/Threading/Once.h"
2122

2223
namespace swift {
2324

25+
/// A template for lazy-initialized values.
26+
/// Usage:
27+
///
28+
/// LazyValue<std::string> value([]() { return createString(); })
29+
/// if (condition) {
30+
/// // 'createString()' is evaluated only when 'value` is dereferenced.
31+
/// doSomething(*value);
32+
/// }
33+
template <typename T, typename Initializer = std::function<T()>>
34+
class LazyValue {
35+
Initializer Init;
36+
llvm::Optional<T> Value;
37+
38+
public:
39+
LazyValue(Initializer Init) : Init(Init){};
40+
41+
T &get() {
42+
if (!Value.hasValue()) {
43+
Value = Init();
44+
}
45+
return Value.value();
46+
}
47+
48+
T *operator->() { return &get(); }
49+
T &operator*() { return get(); }
50+
};
51+
2452
/// A template for lazily-constructed, zero-initialized, leaked-on-exit
2553
/// global objects.
2654
template <class T> class Lazy {

include/swift/Basic/StringExtras.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -490,7 +490,7 @@ class NullTerminatedStringRef {
490490

491491
/// Create a null-terminated string, copying \p Str into \p A .
492492
template <typename Allocator>
493-
NullTerminatedStringRef(StringRef Str, Allocator &A) : Ref() {
493+
NullTerminatedStringRef(StringRef Str, Allocator &A) : Ref("") {
494494
if (Str.empty())
495495
return;
496496

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: 21 additions & 24 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,19 @@ namespace {
53865387
auto macro = cast<MacroDecl>(overload.choice.getDecl());
53875388
ConcreteDeclRef macroRef = resolveConcreteDeclRef(macro, locator);
53885389
E->setMacroRef(macroRef);
5389-
5390-
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.
5390+
E->setType(expandedType);
5391+
5392+
// FIXME: Expansion should be lazy.
5393+
// i.e. 'ExpandMacroExpansionExprRequest' should be sinked into
5394+
// 'getRewritten()', and performed on-demand.
5395+
if (!cs.Options.contains(ConstraintSystemFlags::DisableMacroExpansions) &&
5396+
// Do not expand macros inside macro arguments. For example for
5397+
// '#stringify(#assert(foo))' when typechecking `#assert(foo)`,
5398+
// we don't want to expand it.
5399+
llvm::none_of(makeArrayRef(ExprStack).drop_back(1),
5400+
[](Expr *E) { return isa<MacroExpansionExpr>(E); })) {
5401+
(void)evaluateOrDefault(cs.getASTContext().evaluator,
5402+
ExpandMacroExpansionExprRequest{E}, None);
54065403
}
54075404

54085405
cs.cacheExprTypes(E);

0 commit comments

Comments
 (0)