Skip to content

Commit 040c9e6

Browse files
committed
[macros] add -Rmacro-expansions
This adds the -Rmacro-expansions flag. It provides similar functionality to -dump-macro-expansions, but instead of dumping the macro expansion to stderr, it emits it line by line as remarks. This is useful for testing with -verify, where both macro expansion content and warnings need to be tested at the same time.
1 parent b1c2bc1 commit 040c9e6

File tree

7 files changed

+85
-0
lines changed

7 files changed

+85
-0
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9012,5 +9012,7 @@ GROUPED_WARNING(perf_hint_typealias_uses_existential,ExistentialType,none,
90129012
ERROR(unsafe_self_dependent_result_attr_on_invalid_decl,none,
90139013
"invalid use of @_unsafeSelfDependentResult", ())
90149014

9015+
REMARK(macro_expansion_line, none, "macro content: |%0|", (StringRef))
9016+
90159017
#define UNDEFINE_DIAGNOSTIC_MACROS
90169018
#include "DefineDiagnosticMacros.h"

include/swift/Basic/LangOptions.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -651,6 +651,9 @@ namespace swift {
651651
/// Enables dumping macro expansions.
652652
bool DumpMacroExpansions = false;
653653

654+
/// Emits a remark with the content of each macro expansion line, for matching with -verify
655+
bool RemarkMacroExpansions = false;
656+
654657
/// Enables dumping imports for each SourceFile.
655658
bool DumpSourceFileImports = false;
656659

include/swift/Option/FrontendOptions.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,9 @@ def verify_generic_signatures : Separate<["-"], "verify-generic-signatures">,
185185
MetaVarName<"<module-name>">,
186186
HelpText<"Verify the generic signatures in the given module">;
187187

188+
def expansion_remarks: Flag<["-"], "Rmacro-expansions">,
189+
HelpText<"Show remarks for each line in macro expansions">;
190+
188191
def show_diagnostics_after_fatal : Flag<["-"], "show-diagnostics-after-fatal">,
189192
HelpText<"Keep emitting subsequent diagnostics after a fatal error">;
190193

lib/Frontend/CompilerInvocation.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1774,6 +1774,9 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args,
17741774
Opts.DumpMacroExpansions = Args.hasArg(
17751775
OPT_dump_macro_expansions);
17761776

1777+
Opts.RemarkMacroExpansions = Args.hasArg(
1778+
OPT_expansion_remarks);
1779+
17771780
Opts.DumpSourceFileImports = Args.hasArg(
17781781
OPT_dump_source_file_imports);
17791782

lib/Sema/TypeCheckMacros.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1006,6 +1006,21 @@ static CharSourceRange getExpansionInsertionRange(MacroRole role,
10061006
llvm_unreachable("unhandled MacroRole");
10071007
}
10081008

1009+
static void remarkMacroExpansionsEmitDiags(ASTContext &ctx, unsigned macroBufferID) {
1010+
SourceManager &sourceMgr = ctx.SourceMgr;
1011+
CharSourceRange range = sourceMgr.getRangeForBuffer(macroBufferID);
1012+
SourceLoc start = range.getStart();
1013+
StringRef content(start.getPointer(), range.getByteLength());
1014+
size_t newline;
1015+
do {
1016+
newline = content.find('\n');
1017+
StringRef line = content.take_front(newline);
1018+
content = content.drop_front(newline + 1);
1019+
1020+
ctx.Diags.diagnose(SourceLoc::getFromPointer(line.begin()), diag::macro_expansion_line, line);
1021+
} while (newline != StringRef::npos);
1022+
}
1023+
10091024
static SourceFile *
10101025
createMacroSourceFile(std::unique_ptr<llvm::MemoryBuffer> buffer,
10111026
MacroRole role, ASTNode target, DeclContext *dc,
@@ -1069,6 +1084,10 @@ createMacroSourceFile(std::unique_ptr<llvm::MemoryBuffer> buffer,
10691084
originModule = cast<Decl *>(target)->getModuleContextForNameLookup();
10701085
performImportResolutionForClangMacroBuffer(*macroSourceFile, originModule);
10711086
}
1087+
1088+
if (ctx.LangOpts.RemarkMacroExpansions)
1089+
remarkMacroExpansionsEmitDiags(ctx, macroBufferID);
1090+
10721091
return macroSourceFile;
10731092
}
10741093

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import SwiftSyntax
2+
import SwiftSyntaxBuilder
3+
import SwiftSyntaxMacros
4+
5+
public struct UnstringifyPeerMacro: PeerMacro {
6+
public static func expansion(
7+
of node: AttributeSyntax,
8+
providingPeersOf declaration: some DeclSyntaxProtocol,
9+
in context: some MacroExpansionContext
10+
) throws -> [DeclSyntax] {
11+
do {
12+
let argumentList = node.arguments!.as(LabeledExprListSyntax.self)!
13+
let arguments = [LabeledExprSyntax](argumentList)
14+
let arg = arguments.first!.expression.as(StringLiteralExprSyntax.self)!
15+
let content = arg.representedLiteralValue!
16+
return [DeclSyntax("\(raw: content)")]
17+
}
18+
}
19+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// REQUIRES: swift_swift_parser, executable_test
2+
3+
// RUN: %empty-directory(%t)
4+
// RUN: %host-build-swift -swift-version 5 -emit-library -o %t/%target-library-name(UnstringifyMacroDefinition) -module-name=UnstringifyMacroDefinition %S/Inputs/macro/unstringify-macro.swift -g -no-toolchain-stdlib-rpath
5+
6+
// RUN: %target-typecheck-verify-swift -swift-version 5 -load-plugin-library %t/%target-library-name(UnstringifyMacroDefinition) -Rmacro-expansions
7+
8+
@attached(peer, names: overloaded)
9+
macro unstringifyPeer(_ s: String) =
10+
#externalMacro(module: "UnstringifyMacroDefinition", type: "UnstringifyPeerMacro")
11+
12+
// expected-note@+1 *{{in expansion of macro 'unstringifyPeer' on global function 'foo()' here}}
13+
@unstringifyPeer("func foo(_ x: Int) {\nlet a = 2\nlet b = x\n}")
14+
func foo() {}
15+
/*
16+
expected-expansion@-2:14{{
17+
expected-remark@1{{macro content: |func foo(_ x: Int) {|}}
18+
expected-remark@2{{macro content: | let a = 2|}}
19+
expected-warning@2{{initialization of immutable value 'a' was never used; consider replacing with assignment to '_' or removing it}}
20+
expected-remark@3{{macro content: | let b = x|}}
21+
expected-warning@3{{initialization of immutable value 'b' was never used; consider replacing with assignment to '_' or removing it}}
22+
expected-remark@4{{macro content: |}|}}
23+
}}
24+
*/
25+
26+
@freestanding(expression) public macro ExprMacro() -> String = #file
27+
28+
func bar() {
29+
// expected-note@+1{{in expansion of macro 'ExprMacro' here}}
30+
let _ = #ExprMacro()
31+
/*
32+
expected-expansion@-2:13{{
33+
expected-remark@1{{macro content: |#file|}}
34+
}}
35+
*/
36+
}

0 commit comments

Comments
 (0)