Skip to content

Commit 414ef86

Browse files
committed
[Macros] Type-check and use the result of macro-expanding an expression macro.
Once we have expanded an expression macro, parse and type-check the result given a priori knowledge of the expanded type. Then, create an implicit macro-expansion expression to capture the result of the rewrite.
1 parent f04fd94 commit 414ef86

File tree

5 files changed

+69
-14
lines changed

5 files changed

+69
-14
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6666,5 +6666,12 @@ ERROR(experimental_no_metadata_feature_can_only_be_used_when_enabled,
66666666
" -enable-experimental-feature LayoutPrespecialization to swift to enable "
66676667
" the usage of this language feature", ())
66686668

6669+
6670+
//------------------------------------------------------------------------------
6671+
// MARK: Macros
6672+
//------------------------------------------------------------------------------
6673+
ERROR(expected_macro_expansion_expr,PointsToFirstBadToken,
6674+
"expected macro expansion to produce an expression", ())
6675+
66696676
#define UNDEFINE_DIAGNOSTIC_MACROS
66706677
#include "DefineDiagnosticMacros.h"

lib/AST/ASTDumper.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2982,6 +2982,10 @@ class PrintExpr : public ExprVisitor<PrintExpr> {
29822982
OS << '\n';
29832983
printArgumentList(E->getArgs());
29842984
}
2985+
if (auto rewritten = E->getRewritten()) {
2986+
OS << '\n';
2987+
printRec(rewritten);
2988+
}
29852989
PrintWithColorRAII(OS, ParenthesisColor) << ')';
29862990
}
29872991
};

lib/Sema/CSApply.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2977,8 +2977,14 @@ namespace {
29772977
auto kind = MagicIdentifierLiteralExpr::getKindString(expr->getKind())
29782978
.drop_front();
29792979
auto expandedType = solution.simplifyType(solution.getType(expr));
2980-
if (auto newExpr = expandMacroExpr(dc, expr, kind, expandedType))
2981-
return newExpr;
2980+
if (auto newExpr = expandMacroExpr(dc, expr, kind, expandedType)) {
2981+
auto expansion = new (ctx) MacroExpansionExpr(
2982+
expr->getStartLoc(), expr, nullptr, /*isImplicit=*/true,
2983+
expandedType);
2984+
expansion->setRewritten(newExpr);
2985+
cs.cacheExprTypes(expansion);
2986+
return expansion;
2987+
}
29822988

29832989
// Fall through to use old implementation.
29842990
}

lib/Sema/TypeCheckMacros.cpp

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,13 @@
1515
//===----------------------------------------------------------------------===//
1616

1717
#include "TypeCheckMacros.h"
18+
#include "TypeChecker.h"
1819
#include "swift/AST/ASTContext.h"
1920
#include "swift/AST/Expr.h"
2021
#include "swift/AST/SourceFile.h"
2122
#include "swift/Basic/SourceManager.h"
2223
#include "swift/Parse/Lexer.h"
24+
#include "swift/Parse/Parser.h"
2325

2426
using namespace swift;
2527

@@ -74,7 +76,7 @@ Expr *swift::expandMacroExpr(
7476
std::tie(endLine, endColumn) =
7577
sourceMgr.getLineAndColumnInBuffer(endLoc, *bufferID);
7678

77-
out << sourceMgr.getIdentifierForBuffer(*bufferID) << ":"
79+
out << " in " << sourceMgr.getIdentifierForBuffer(*bufferID) << ":"
7880
<< startLine << ":" << startColumn
7981
<< "-" << endLine << ":" << endColumn;
8082
}
@@ -86,13 +88,39 @@ Expr *swift::expandMacroExpr(
8688
StringRef(evaluatedSource, evaluatedSourceLength), bufferName);
8789
unsigned macroBufferID = sourceMgr.addNewSourceBuffer(std::move(macroBuffer));
8890

89-
// FIXME: Debug output.
90-
llvm::outs() << "Macro rewrite: "
91-
<< "#" << macroName
92-
<< " --> " << sourceMgr.getEntireTextForBuffer(macroBufferID)
93-
<< "\n";
91+
// Create a source file to hold the macro buffer.
92+
// FIXME: Seems like we should record this somewhere?
93+
auto macroSourceFile = new (ctx) SourceFile(
94+
*dc->getParentModule(), SourceFileKind::Library, macroBufferID);
95+
96+
// Parse the expression.
97+
Parser parser(macroBufferID, *macroSourceFile, &ctx.Diags, nullptr, nullptr);
98+
parser.consumeTokenWithoutFeedingReceiver();
99+
auto parsedResult = parser.parseExpr(diag::expected_macro_expansion_expr);
100+
if (parsedResult.isParseError() || parsedResult.isNull()) {
101+
// Tack on a note to say where we expanded the macro from?
102+
return nullptr;
103+
}
104+
105+
// Type-check the expanded expression.
106+
// FIXME: Would like to pass through type checking options like "discarded"
107+
// that are captured by TypeCheckExprOptions.
108+
Expr *expandedExpr = parsedResult.get();
109+
constraints::ContextualTypeInfo contextualType {
110+
TypeLoc::withoutLoc(expandedType),
111+
// FIXME: Add a contextual type purpose for macro expansion.
112+
ContextualTypePurpose::CTP_CoerceOperand
113+
};
114+
115+
Type realExpandedType = TypeChecker::typeCheckExpression(
116+
expandedExpr, dc, contextualType);
117+
if (!realExpandedType)
118+
return nullptr;
94119

95-
return nullptr;
120+
assert((expandedType->isEqual(realExpandedType) ||
121+
realExpandedType->hasError()) &&
122+
"Type checking changed the result type?");
123+
return expandedExpr;
96124
}
97125

98126
#endif // SWIFT_SWIFT_PARSER

test/Macros/builtin_macros.swift

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,22 @@
1-
// RUN: %target-swift-frontend -enable-experimental-feature BuiltinMacros -typecheck %s -module-name MacrosTest 2>&1 | %FileCheck %s
1+
// RUN: %target-swift-frontend -enable-experimental-feature BuiltinMacros -dump-ast %s -module-name MacrosTest 2>&1 | %FileCheck %s
22
// REQUIRES: OS=macosx
33

4-
// CHECK: #function --> "MacrosTest"
4+
// CHECK: macro_expansion_expr implicit type='String'
5+
// CHECK-NEXT: magic_identifier_literal_expr{{.*}}kind=#function
6+
// CHECK-NEXT: string_literal_expr{{.*}}Macro expansion of #function in{{.*}}value="MacrosTest"
57
print(#function)
68

79
func f(a: Int, b: Int) {
810
print(#function, #line, #column)
9-
// CHECK-NEXT: #function --> "f(a:b:)"
10-
// CHECK-NEXT: #line --> 8
11-
// CHECK-NEXT: #column --> 27
11+
// CHECK: macro_expansion_expr implicit type='String'
12+
// CHECK-NEXT: magic_identifier_literal_expr{{.*}}kind=#function
13+
// CHECK-NEXT: string_literal_expr{{.*}}Macro expansion of #function in{{.*}}value="f(a:b:)"
14+
15+
// CHECK: macro_expansion_expr implicit type='Int'
16+
// CHECK-NEXT: magic_identifier_literal_expr{{.*}}kind=#line
17+
// CHECK-NEXT: integer_literal_expr{{.*}}Macro expansion of #line in{{.*}}value=10
18+
19+
// CHECK: macro_expansion_expr implicit type='Int'
20+
// CHECK-NEXT: magic_identifier_literal_expr{{.*}}kind=#column
21+
// CHECK-NEXT: integer_literal_expr{{.*}}Macro expansion of #column in{{.*}}value=27
1222
}

0 commit comments

Comments
 (0)