Fixes crash while instrumenting generic func body embedded in another func.

The crash was caused by attempting to add logging expressions that capture generic variables while using the outer func decl context that was not the generic decl context of the inner (generic) func.

The fix "pushes" the current func decl context while instrumenting the body. Rather than always using the top-level func decl context for all nested func bodies.
This commit is contained in:
Chris Miles
2025-01-10 14:54:52 -08:00
parent 577945df01
commit f2846ce2cb
3 changed files with 43 additions and 0 deletions

View File

@@ -339,7 +339,12 @@ public:
if (auto *FD = dyn_cast<FuncDecl>(D)) {
if (BraceStmt *B = FD->getTypecheckedBody()) {
const ParameterList *PL = FD->getParameters();
// Use FD's DeclContext as TypeCheckDC for transforms in func body
// then swap back TypeCheckDC at end of scope.
llvm::SaveAndRestore<DeclContext *> localDC(TypeCheckDC, FD);
BraceStmt *NB = transformBraceStmt(B, PL);
// Since it would look strange going straight to the first line in a
// function body, we throw in a before/after pointing at the function
// decl at the start of the transformed body

View File

@@ -312,6 +312,11 @@ public:
if (BraceStmt *B = FD->getTypecheckedBody()) {
const ParameterList *PL = FD->getParameters();
TargetKindSetter TKS(BracePairs, BracePair::TargetKinds::Return);
// Use FD's DeclContext as TypeCheckDC for transforms in func body
// then swap back TypeCheckDC at end of scope.
llvm::SaveAndRestore<DeclContext *> localDC(TypeCheckDC, FD);
BraceStmt *NB = transformBraceStmt(B, PL);
if (NB != B) {
FD->setBody(NB, AbstractFunctionDecl::BodyKind::TypeChecked);

View File

@@ -0,0 +1,33 @@
// RUN: %empty-directory(%t)
// Build PlaygroundSupport module
// RUN: %target-build-swift -whole-module-optimization -module-name PlaygroundSupport -emit-module-path %t/PlaygroundSupport.swiftmodule -parse-as-library -c -o %t/PlaygroundSupport.o %S/Inputs/SilentPCMacroRuntime.swift %S/Inputs/PlaygroundsRuntime.swift
// RUN: %target-build-swift -swift-version 5 -emit-module -Xfrontend -playground -I=%t %s
// RUN: %target-build-swift -swift-version 6 -emit-module -Xfrontend -playground -I=%t %s
// RUN: %target-build-swift -swift-version 5 -emit-module -Xfrontend -playground -Xfrontend -pc-macro -I=%t %s
// RUN: %target-build-swift -swift-version 6 -emit-module -Xfrontend -playground -Xfrontend -pc-macro -I=%t %s
// REQUIRES: executable_test
import PlaygroundSupport
func test1() {
func buildBlock<Content>(content: Content) {
content
}
}
func test2() {
func buildBlock<Content>(content: Content) -> Content {
content
return content
}
}
func test3<Content>(_ content: Content) {
func buildBlock<Content2>(_ content2: Content2) -> Content2 {
return content2
}
}