Skip to content

Commit 6bb9cb8

Browse files
committedJan 3, 2023
[Macros] Always parse macro expansions, diagnose later
Always parse macro expansions, regardless of language mode, and eliminate the fallback path for very, very, very old object literals like `#Color`. Instead, check for the feature flag for macro declaration and at macro expansion time, since this is a semantic restriction. While here, refactor things so the vast majority of the macro-handling logic still applies even if the Swift Swift parser is disabled. Only attempts to expand the macro will fail. This allows us to enable the macro-diagnostics test everywhere.
1 parent 71ca9c8 commit 6bb9cb8

20 files changed

+99
-211
lines changed
 

‎include/swift/AST/DiagnosticsCommon.def

+2
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,8 @@ ERROR(unknown_attribute,none,
219219
//------------------------------------------------------------------------------
220220
NOTE(in_macro_expansion,none,
221221
"in expansion of macro %0 here", (DeclName))
222+
ERROR(macro_experimental,none,
223+
"macros are an experimental feature that is not enabled", ())
222224

223225
//------------------------------------------------------------------------------
224226
// MARK: bridged diagnostics

‎include/swift/AST/DiagnosticsParse.def

-3
Original file line numberDiff line numberDiff line change
@@ -1329,9 +1329,6 @@ ERROR(expected_rsquare_array_expr,PointsToFirstBadToken,
13291329
// Object literal expressions
13301330
ERROR(expected_arg_list_in_object_literal,PointsToFirstBadToken,
13311331
"expected argument list in object literal", ())
1332-
ERROR(legacy_object_literal,none,
1333-
"'%select{|[}0#%1(...)%select{|#]}0' has been renamed to '#%2(...)'",
1334-
(bool, StringRef, StringRef))
13351332

13361333
// Unknown pound expression.
13371334
ERROR(unknown_pound_expr,none,

‎include/swift/AST/DiagnosticsSema.def

+3-2
Original file line numberDiff line numberDiff line change
@@ -6762,8 +6762,7 @@ ERROR(experimental_no_metadata_feature_can_only_be_used_when_enabled,
67626762
ERROR(expected_macro_expansion_expr,PointsToFirstBadToken,
67636763
"expected macro expansion to produce an expression", ())
67646764
ERROR(macro_undefined,PointsToFirstBadToken,
6765-
"macro %0 is undefined; use `-load-plugin-library` to specify dynamic "
6766-
"libraries that contain this macro", (Identifier))
6765+
"no macro named %0", (Identifier))
67676766
ERROR(external_macro_not_found,none,
67686767
"external macro implementation type '%0.%1' could not be found for "
67696768
"macro %2; the type must be public and provided via "
@@ -6798,6 +6797,8 @@ ERROR(macro_expansion_missing_pound,none,
67986797
"expansion of macro %0 requires leading '#'", (DeclName))
67996798
ERROR(macro_expansion_missing_arguments,none,
68006799
"expansion of macro %0 requires arguments", (DeclName))
6800+
ERROR(macro_unsupported,none,
6801+
"macros are not supported in this compiler", ())
68016802

68026803
//------------------------------------------------------------------------------
68036804
// MARK: Move Only Errors

‎include/swift/Parse/Parser.h

-1
Original file line numberDiff line numberDiff line change
@@ -1748,7 +1748,6 @@ class Parser {
17481748
ParserResult<Expr> parseExprMacroExpansion(bool isExprBasic);
17491749
ParserResult<Expr> parseExprCollection();
17501750
ParserResult<Expr> parseExprCollectionElement(Optional<bool> &isDictionary);
1751-
ParserResult<Expr> parseExprPoundUnknown(SourceLoc LSquareLoc);
17521751
ParserResult<Expr>
17531752
parseExprPoundCodeCompletion(Optional<StmtKind> ParentKind);
17541753

‎lib/Parse/ParseDecl.cpp

+4-4
Original file line numberDiff line numberDiff line change
@@ -4844,11 +4844,11 @@ Parser::parseDecl(ParseDeclOptions Flags,
48444844
consumeToken(tok::code_complete);
48454845
DeclResult = makeParserCodeCompletionResult<Decl>();
48464846
break;
4847-
} else if (Context.LangOpts.hasFeature(Feature::Macros)) {
4848-
DeclResult = parseDeclMacroExpansion(Flags, Attributes);
4849-
break;
48504847
}
4851-
LLVM_FALLTHROUGH;
4848+
4849+
// Parse as a macro expansion.
4850+
DeclResult = parseDeclMacroExpansion(Flags, Attributes);
4851+
break;
48524852

48534853
case tok::pound_if:
48544854
case tok::pound_sourceLocation:

‎lib/Parse/ParseExpr.cpp

+2-92
Original file line numberDiff line numberDiff line change
@@ -1774,14 +1774,8 @@ ParserResult<Expr> Parser::parseExprPrimary(Diag<> ID, bool isExprBasic) {
17741774
Tok.getLoc().getAdvancedLoc(1) == peekToken().getLoc()) {
17751775
return parseExprPoundCodeCompletion(/*ParentKind*/None);
17761776
}
1777-
if (Context.LangOpts.hasFeature(Feature::Macros)) {
1778-
return parseExprMacroExpansion(isExprBasic);
1779-
}
1780-
if (peekToken().is(tok::identifier) && !peekToken().isEscapedIdentifier() &&
1781-
Tok.getLoc().getAdvancedLoc(1) == peekToken().getLoc()) {
1782-
return parseExprPoundUnknown(SourceLoc());
1783-
}
1784-
goto UnknownCharacter;
1777+
1778+
return parseExprMacroExpansion(isExprBasic);
17851779

17861780
// Eat an invalid token in an expression context. Error tokens are diagnosed
17871781
// by the lexer, so there is no reason to emit another diagnostic.
@@ -3245,82 +3239,6 @@ Parser::parseExprObjectLiteral(ObjectLiteralExpr::LiteralKind LitKind,
32453239
/*implicit*/ false));
32463240
}
32473241

3248-
/// Parse and diagnose unknown pound expression
3249-
///
3250-
/// If it look like a legacy (Swift 2) object literal expression, suggest fix-it
3251-
/// to use new object literal syntax.
3252-
///
3253-
/// expr-unknown-pound:
3254-
/// '#' identifier expr-paren?
3255-
/// '[' '#' identifier expr-paren? '#' ']' ; Legacy object literal
3256-
ParserResult<Expr> Parser::parseExprPoundUnknown(SourceLoc LSquareLoc) {
3257-
SourceLoc PoundLoc = consumeToken(tok::pound);
3258-
3259-
assert(Tok.is(tok::identifier) && !Tok.isEscapedIdentifier() &&
3260-
PoundLoc.getAdvancedLoc(1) == Tok.getLoc());
3261-
3262-
Identifier Name;
3263-
SourceLoc NameLoc = consumeIdentifier(Name, /*diagnoseDollarPrefix=*/false);
3264-
3265-
// Parse arguments if exist.
3266-
ArgumentList *ArgList = nullptr;
3267-
if (Tok.isFollowingLParen()) {
3268-
// Parse arguments.
3269-
auto result = parseArgumentList(tok::l_paren, tok::r_paren,
3270-
/*isExprBasic*/ true);
3271-
if (result.hasCodeCompletion())
3272-
return makeParserCodeCompletionResult<Expr>();
3273-
if (result.isParseErrorOrHasCompletion())
3274-
return makeParserError();
3275-
ArgList = result.get();
3276-
}
3277-
3278-
std::pair<StringRef, StringRef> NewNameArgPair =
3279-
llvm::StringSwitch<std::pair<StringRef, StringRef>>(Name.str())
3280-
.Case("Color", {"colorLiteral", "red"})
3281-
.Case("Image", {"imageLiteral", "resourceName"})
3282-
.Case("FileReference", {"fileLiteral", "resourceName"})
3283-
.Default({});
3284-
3285-
// If it's not legacy object literal, we don't know how to handle this.
3286-
if (NewNameArgPair.first.empty()) {
3287-
diagnose(PoundLoc, diag::unknown_pound_expr, Name.str());
3288-
return makeParserError();
3289-
}
3290-
3291-
// Diagnose legacy object literal.
3292-
3293-
// Didn't have arguments.
3294-
if (!ArgList || ArgList->getLParenLoc().isInvalid()) {
3295-
diagnose(Tok.getLoc(), diag::expected_arg_list_in_object_literal);
3296-
return makeParserError();
3297-
}
3298-
3299-
// If it's started with '[', try to parse closing '#]'.
3300-
SourceLoc RPoundLoc, RSquareLoc;
3301-
if (LSquareLoc.isValid() && consumeIf(tok::pound, RPoundLoc))
3302-
consumeIf(tok::r_square, RSquareLoc);
3303-
3304-
auto diag = diagnose(LSquareLoc.isValid() ? LSquareLoc : PoundLoc,
3305-
diag::legacy_object_literal, LSquareLoc.isValid(),
3306-
Name.str(), NewNameArgPair.first);
3307-
3308-
// Remove '[' if exist.
3309-
if (LSquareLoc.isValid())
3310-
diag.fixItRemove(LSquareLoc);
3311-
// Replace the literal name.
3312-
diag.fixItReplace(NameLoc, NewNameArgPair.first);
3313-
// Replace the first argument.
3314-
if (!ArgList->empty() && ArgList->front().getLabelLoc().isValid())
3315-
diag.fixItReplace(ArgList->front().getLabelLoc(), NewNameArgPair.second);
3316-
// Remove '#]' if exist.
3317-
if (RPoundLoc.isValid())
3318-
diag.fixItRemove(
3319-
{RPoundLoc, RSquareLoc.isValid() ? RSquareLoc : RPoundLoc});
3320-
3321-
return makeParserError();
3322-
}
3323-
33243242
/// Handle code completion after pound in expression position.
33253243
///
33263244
/// In case it's in a stmt condition position, specify \p ParentKind to
@@ -3460,14 +3378,6 @@ ParserResult<Expr> Parser::parseExprCollection() {
34603378
DictionaryExpr::create(Context, LSquareLoc, {}, {}, RSquareLoc));
34613379
}
34623380

3463-
// [#identifier is likely to be a legacy object literal.
3464-
if (Tok.is(tok::pound) && peekToken().is(tok::identifier) &&
3465-
!peekToken().isEscapedIdentifier() &&
3466-
LSquareLoc.getAdvancedLoc(1) == Tok.getLoc() &&
3467-
Tok.getLoc().getAdvancedLoc(1) == peekToken().getLoc()) {
3468-
return parseExprPoundUnknown(LSquareLoc);
3469-
}
3470-
34713381
ParserStatus Status;
34723382
Optional<bool> isDictionary;
34733383
SmallVector<Expr *, 8> ElementExprs;

‎lib/Sema/CSApply.cpp

+11-17
Original file line numberDiff line numberDiff line change
@@ -5387,27 +5387,21 @@ namespace {
53875387
}
53885388

53895389
Expr *visitMacroExpansionExpr(MacroExpansionExpr *E) {
5390-
#if SWIFT_SWIFT_PARSER
5391-
auto &ctx = cs.getASTContext();
5392-
if (ctx.LangOpts.hasFeature(Feature::Macros)) {
5393-
auto expandedType = solution.simplifyType(solution.getType(E));
5394-
cs.setType(E, expandedType);
5390+
auto expandedType = solution.simplifyType(solution.getType(E));
5391+
cs.setType(E, expandedType);
53955392

5396-
auto locator = cs.getConstraintLocator(E);
5397-
auto overload = solution.getOverloadChoice(locator);
5393+
auto locator = cs.getConstraintLocator(E);
5394+
auto overload = solution.getOverloadChoice(locator);
53985395

5399-
auto macro = cast<MacroDecl>(overload.choice.getDecl());
5400-
ConcreteDeclRef macroRef = resolveConcreteDeclRef(macro, locator);
5401-
E->setMacroRef(macroRef);
5396+
auto macro = cast<MacroDecl>(overload.choice.getDecl());
5397+
ConcreteDeclRef macroRef = resolveConcreteDeclRef(macro, locator);
5398+
E->setMacroRef(macroRef);
54025399

5403-
if (auto newExpr = expandMacroExpr(dc, E, macroRef, expandedType)) {
5404-
E->setRewritten(newExpr);
5405-
cs.cacheExprTypes(E);
5406-
return E;
5407-
}
5408-
// Fall through to use old implementation.
5400+
if (auto newExpr = expandMacroExpr(dc, E, macroRef, expandedType)) {
5401+
E->setRewritten(newExpr);
5402+
cs.cacheExprTypes(E);
54095403
}
5410-
#endif
5404+
54115405
return E;
54125406
}
54135407

‎lib/Sema/CSGen.cpp

+47-52
Original file line numberDiff line numberDiff line change
@@ -3779,67 +3779,62 @@ namespace {
37793779
}
37803780

37813781
Type visitMacroExpansionExpr(MacroExpansionExpr *expr) {
3782-
#if SWIFT_SWIFT_PARSER
37833782
auto &ctx = CS.getASTContext();
3784-
if (ctx.LangOpts.hasFeature(Feature::Macros)) {
3785-
auto locator = CS.getConstraintLocator(expr);
3786-
3787-
// For calls, set up the argument list.
3788-
bool isCall = expr->getArgs() != nullptr;
3789-
if (isCall) {
3790-
CS.associateArgumentList(locator, expr->getArgs());
3791-
}
3783+
auto locator = CS.getConstraintLocator(expr);
37923784

3793-
// Look up the macros with this name.
3794-
auto macroIdent = expr->getMacroName().getBaseIdentifier();
3795-
FunctionRefKind functionRefKind = isCall ? FunctionRefKind::SingleApply
3796-
: FunctionRefKind::Unapplied;
3797-
auto macros = lookupMacros(
3798-
macroIdent, expr->getMacroNameLoc().getBaseNameLoc(),
3799-
functionRefKind);
3800-
if (macros.empty()) {
3801-
ctx.Diags.diagnose(expr->getMacroNameLoc(), diag::macro_undefined,
3802-
macroIdent)
3803-
.highlight(expr->getMacroNameLoc().getSourceRange());
3804-
return Type();
3805-
}
3785+
// For calls, set up the argument list.
3786+
bool isCall = expr->getArgs() != nullptr;
3787+
if (isCall) {
3788+
CS.associateArgumentList(locator, expr->getArgs());
3789+
}
3790+
3791+
// Look up the macros with this name.
3792+
auto macroIdent = expr->getMacroName().getBaseIdentifier();
3793+
FunctionRefKind functionRefKind = isCall ? FunctionRefKind::SingleApply
3794+
: FunctionRefKind::Unapplied;
3795+
auto macros = lookupMacros(
3796+
macroIdent, expr->getMacroNameLoc().getBaseNameLoc(),
3797+
functionRefKind);
3798+
if (macros.empty()) {
3799+
ctx.Diags.diagnose(expr->getMacroNameLoc(), diag::macro_undefined,
3800+
macroIdent)
3801+
.highlight(expr->getMacroNameLoc().getSourceRange());
3802+
return Type();
3803+
}
38063804

3807-
// Introduce an overload set for the macro reference.
3808-
auto macroRefType = Type(CS.createTypeVariable(locator, 0));
3809-
CS.addOverloadSet(macroRefType, macros, CurDC, locator);
3805+
// Introduce an overload set for the macro reference.
3806+
auto macroRefType = Type(CS.createTypeVariable(locator, 0));
3807+
CS.addOverloadSet(macroRefType, macros, CurDC, locator);
38103808

3811-
// Add explicit generic arguments, if there were any.
3812-
if (expr->getGenericArgsRange().isValid()) {
3813-
if (addSpecializationConstraint(
3814-
CS.getConstraintLocator(expr), macroRefType,
3815-
expr->getGenericArgs()))
3816-
return Type();
3817-
}
3809+
// Add explicit generic arguments, if there were any.
3810+
if (expr->getGenericArgsRange().isValid()) {
3811+
if (addSpecializationConstraint(
3812+
CS.getConstraintLocator(expr), macroRefType,
3813+
expr->getGenericArgs()))
3814+
return Type();
3815+
}
38183816

3819-
// For non-calls, the type variable is the result.
3820-
if (!isCall)
3821-
return macroRefType;
3817+
// For non-calls, the type variable is the result.
3818+
if (!isCall)
3819+
return macroRefType;
38223820

3823-
// For calls, form the applicable-function constraint. The result type
3824-
// is the result of that call.
3825-
SmallVector<AnyFunctionType::Param, 8> params;
3826-
getMatchingParams(expr->getArgs(), params);
3821+
// For calls, form the applicable-function constraint. The result type
3822+
// is the result of that call.
3823+
SmallVector<AnyFunctionType::Param, 8> params;
3824+
getMatchingParams(expr->getArgs(), params);
38273825

3828-
Type resultType = CS.createTypeVariable(
3829-
CS.getConstraintLocator(expr, ConstraintLocator::FunctionResult),
3830-
TVO_CanBindToNoEscape);
3826+
Type resultType = CS.createTypeVariable(
3827+
CS.getConstraintLocator(expr, ConstraintLocator::FunctionResult),
3828+
TVO_CanBindToNoEscape);
38313829

3832-
CS.addConstraint(
3833-
ConstraintKind::ApplicableFunction,
3834-
FunctionType::get(params, resultType),
3835-
macroRefType,
3836-
CS.getConstraintLocator(
3837-
expr, ConstraintLocator::ApplyFunction));
3830+
CS.addConstraint(
3831+
ConstraintKind::ApplicableFunction,
3832+
FunctionType::get(params, resultType),
3833+
macroRefType,
3834+
CS.getConstraintLocator(
3835+
expr, ConstraintLocator::ApplyFunction));
38383836

3839-
return resultType;
3840-
}
3841-
#endif
3842-
return Type();
3837+
return resultType;
38433838
}
38443839

38453840
static bool isTriggerFallbackDiagnosticBuiltin(UnresolvedDotExpr *UDE,

‎lib/Sema/TypeCheckDeclPrimary.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -1998,6 +1998,8 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
19981998
TypeChecker::checkDeclAttributes(MD);
19991999
checkAccessControl(MD);
20002000

2001+
if (!Ctx.LangOpts.hasFeature(Feature::Macros))
2002+
MD->diagnose(diag::macro_experimental);
20012003
if (!MD->getDeclContext()->isModuleScopeContext())
20022004
MD->diagnose(diag::macro_in_nested, MD->getName());
20032005
if (!MD->getMacroContexts())

‎lib/Sema/TypeCheckMacros.cpp

+11-3
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,6 @@ MacroDefinition MacroDefinitionRequest::evaluate(
121121
ctx, macro->externalModuleName, macro->externalMacroTypeName);
122122
}
123123

124-
#if SWIFT_SWIFT_PARSER
125124
Expr *swift::expandMacroExpr(
126125
DeclContext *dc, Expr *expr, ConcreteDeclRef macroRef, Type expandedType
127126
) {
@@ -157,6 +156,13 @@ Expr *swift::expandMacroExpr(
157156
}
158157

159158
case MacroDefinition::ImplementationKind::InProcess: {
159+
// Make sure macros are enabled before we expand.
160+
if (!ctx.LangOpts.hasFeature(Feature::Macros)) {
161+
ctx.Diags.diagnose(expr->getLoc(), diag::macro_experimental);
162+
return nullptr;
163+
}
164+
165+
#if SWIFT_SWIFT_PARSER
160166
PrettyStackTraceExpr debugStack(ctx, "expanding macro", expr);
161167

162168
// Builtin macros are handled via ASTGen.
@@ -176,6 +182,10 @@ Expr *swift::expandMacroExpr(
176182
evaluatedSource = NullTerminatedStringRef(evaluatedSourceAddress,
177183
(size_t)evaluatedSourceLength);
178184
break;
185+
#else
186+
ctx.Diags.diagnose(expr->getLoc(), diag::macro_unsupported);
187+
return nullptr;
188+
#endif
179189
}
180190
}
181191

@@ -266,5 +276,3 @@ Expr *swift::expandMacroExpr(
266276
"Type checking changed the result type?");
267277
return expandedExpr;
268278
}
269-
270-
#endif // SWIFT_SWIFT_PARSER

‎lib/Sema/TypeCheckMacros.h

-4
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,6 @@ namespace swift {
2424
class Expr;
2525
class TypeRepr;
2626

27-
#if SWIFT_SWIFT_PARSER
28-
2927
/// Expands the given macro expression and type-check the result with
3028
/// the given expanded type.
3129
///
@@ -34,8 +32,6 @@ class TypeRepr;
3432
Expr *expandMacroExpr(
3533
DeclContext *dc, Expr *expr, ConcreteDeclRef macroRef, Type expandedType);
3634

37-
#endif // SWIFT_SWIFT_PARSER
38-
3935
} // end namespace swift
4036

4137
#endif /* SWIFT_SEMA_TYPECHECKMACROS_H */

0 commit comments

Comments
 (0)