Skip to content

Commit ea35e1b

Browse files
committed
Use Swift Syntax for checking literals
1 parent 865bf1e commit ea35e1b

File tree

5 files changed

+64
-17
lines changed

5 files changed

+64
-17
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7526,9 +7526,6 @@ ERROR(macro_attached_to_invalid_decl,none,
75267526
ERROR(macro_as_default_argument, none,
75277527
"non-built-in macro cannot be used as default argument",
75287528
())
7529-
ERROR(macro_as_default_argument_arguments_must_be_literal, none,
7530-
"argument to macro used as default argument must be literal",
7531-
())
75327529
ERROR(conformance_macro,none,
75337530
"conformance macros are replaced by extension macros",
75347531
())

include/swift/Bridging/ASTGen.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,10 @@ void *_Nonnull swift_ASTGen_resolveExecutableMacro(
6868
void *_Nonnull opaquePluginHandle);
6969
void swift_ASTGen_destroyExecutableMacro(void *_Nonnull macro);
7070

71+
bool swift_ASTGen_checkDefaultArgumentMacroExpression(
72+
void *_Nonnull diagEngine, void *_Nonnull sourceFile,
73+
const void *_Nonnull macroSourceLocation);
74+
7175
ptrdiff_t swift_ASTGen_checkMacroDefinition(
7276
void *_Nonnull diagEngine, void *_Nonnull sourceFile,
7377
const void *_Nonnull macroSourceLocation,

lib/ASTGen/Sources/ASTGen/Macros.swift

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,53 @@ fileprivate func identifierFromStringLiteral(_ node: ExprSyntax) -> String? {
179179
return stringSegment.content.text
180180
}
181181

182+
/// Checks if the macro expression used as an default argument has any issues.
183+
///
184+
/// - Returns: `true` if all restrictions are satisfied, `false` if diagnostics
185+
/// are emitted.
186+
@_cdecl("swift_ASTGen_checkDefaultArgumentMacroExpression")
187+
func checkDefaultArgumentMacroExpression(
188+
diagEnginePtr: UnsafeMutableRawPointer,
189+
sourceFilePtr: UnsafeRawPointer,
190+
macroLocationPtr: UnsafePointer<UInt8>
191+
) -> Bool {
192+
let sourceFilePtr = sourceFilePtr.bindMemory(to: ExportedSourceFile.self, capacity: 1)
193+
194+
// Find the macro expression.
195+
guard
196+
let macroExpr = findSyntaxNodeInSourceFile(
197+
sourceFilePtr: sourceFilePtr,
198+
sourceLocationPtr: macroLocationPtr,
199+
type: MacroExpansionExprSyntax.self
200+
)
201+
else {
202+
// FIXME: Produce an error
203+
return false
204+
}
205+
206+
do {
207+
try macroExpr.checkDefaultArgumentMacroExpression()
208+
return true
209+
} catch let errDiags as DiagnosticsError {
210+
let srcMgr = SourceManager(cxxDiagnosticEngine: diagEnginePtr)
211+
srcMgr.insert(sourceFilePtr)
212+
for diag in errDiags.diagnostics {
213+
srcMgr.diagnose(diagnostic: diag)
214+
}
215+
return false
216+
} catch let error {
217+
let srcMgr = SourceManager(cxxDiagnosticEngine: diagEnginePtr)
218+
srcMgr.insert(sourceFilePtr)
219+
srcMgr.diagnose(
220+
diagnostic: .init(
221+
node: macroExpr,
222+
message: ASTGenMacroDiagnostic.thrownError(error)
223+
)
224+
)
225+
return false
226+
}
227+
}
228+
182229
/// Check a macro definition, producing a description of that macro definition
183230
/// for use in macro expansion.
184231
///

lib/Sema/TypeCheckDeclPrimary.cpp

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
#include "swift/AST/TypeWalker.h"
5555
#include "swift/Basic/Defer.h"
5656
#include "swift/Basic/Statistic.h"
57+
#include "swift/Bridging/ASTGen.h"
5758
#include "swift/Parse/Lexer.h"
5859
#include "swift/Parse/Parser.h"
5960
#include "swift/Serialization/SerializedModuleLoader.h"
@@ -1033,18 +1034,16 @@ static bool checkExpressionMacroDefaultValueRestrictions(ParamDecl *param) {
10331034
return false;
10341035
}
10351036

1036-
auto macroExpansionExpr = cast<MacroExpansionExpr>(initExpr);
1037-
// only allow arguments that are literals
1038-
auto args = macroExpansionExpr->getArgs();
1039-
for (auto arg : *args)
1040-
if (!isa<LiteralExpr>(arg.getExpr()) ||
1041-
isa<InterpolatedStringLiteralExpr>(arg.getExpr())) {
1042-
ctx.Diags.diagnose(
1043-
arg.getExpr()->getLoc(),
1044-
diag::macro_as_default_argument_arguments_must_be_literal);
1045-
return false;
1046-
}
1047-
return true;
1037+
#if SWIFT_BUILD_SWIFT_SYNTAX
1038+
auto *DC = param->getInnermostDeclContext();
1039+
const SourceFile *SF = DC->getParentSourceFile();
1040+
return swift_ASTGen_checkDefaultArgumentMacroExpression(
1041+
&ctx.Diags, SF->getExportedSourceFile(),
1042+
initExpr->getLoc().getOpaquePointerValue());
1043+
#else
1044+
ctx.Diags.diagnose(initExpr->getLoc(), diag::macro_unsupported));
1045+
return false;
1046+
#endif
10481047
}
10491048

10501049
void TypeChecker::notePlaceholderReplacementTypes(Type writtenType,

test/Macros/macro_default_argument_diagnostics.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,10 @@ func testObject(color: Stringified<MyLiteral> = #stringify(#colorLiteral(red: 0.
5050

5151
let myString = "oops"
5252

53-
// expected-error@+1{{argument to macro used as default argument must be literal}}
53+
// expected-error@+1{{only literals are permitted}}
5454
func testIdentifier(notOkay: Stringified<String> = #stringify(myString)) {}
5555

56-
// expected-error@+1{{argument to macro used as default argument must be literal}}
56+
// expected-error@+1{{only literals are permitted}}
5757
func testString(interpolated: Stringified<String> = #stringify("Hello \(0b10001)")) {}
5858

5959
// expected-error@+1{{macro 'stringify' is internal and cannot be referenced from a default argument value}}

0 commit comments

Comments
 (0)