Skip to content

Commit 4d7df08

Browse files
authored
Merge pull request #83387 from swiftlang/private-fileid-not-retroactive
[cxx-interop] Do not consider extensions blessed by SWIFT_PRIVATE_FILEID to be retroactive
2 parents 3db1a66 + 0e4575e commit 4d7df08

File tree

2 files changed

+67
-0
lines changed

2 files changed

+67
-0
lines changed

lib/AST/ProtocolConformance.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,12 @@
2828
#include "swift/AST/Module.h"
2929
#include "swift/AST/NameLookup.h"
3030
#include "swift/AST/PackConformance.h"
31+
#include "swift/AST/Type.h"
3132
#include "swift/AST/TypeCheckRequests.h"
3233
#include "swift/AST/Types.h"
3334
#include "swift/Basic/Assertions.h"
3435
#include "swift/Basic/Statistic.h"
36+
#include "swift/ClangImporter/ClangImporter.h"
3537
#include "llvm/ADT/Statistic.h"
3638
#include "llvm/Support/PrettyStackTrace.h"
3739
#include "llvm/Support/SaveAndRestore.h"
@@ -248,6 +250,18 @@ bool ProtocolConformance::isRetroactive() const {
248250
if (isSameRetroactiveContext(extensionModule, conformingTypeModule)) {
249251
return false;
250252
}
253+
254+
auto *useSF = getDeclContext()->getOutermostParentSourceFile();
255+
auto blessesSF = [&](auto &blessed) {
256+
auto blessedFileID = SourceFile::FileIDStr::parse(blessed.first);
257+
return blessedFileID && blessedFileID->matches(useSF);
258+
};
259+
auto *clangDecl = dyn_cast_or_null<clang::CXXRecordDecl>(
260+
conformingTypeDecl->getClangDecl());
261+
if (clangDecl &&
262+
llvm::any_of(importer::getPrivateFileIDAttrs(clangDecl), blessesSF)) {
263+
return false;
264+
}
251265
}
252266

253267
return true;
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// RUN: split-file %s %t
2+
// RUN: %target-swift-frontend -typecheck -verify -I %t/Cxx/include %t/PrivateFile.swift -cxx-interoperability-mode=default -module-name Module
3+
// RUN: %target-swift-frontend -typecheck -verify -I %t/Cxx/include %t/HasRetroactive.swift -cxx-interoperability-mode=default -module-name Module
4+
// RUN: %target-swift-frontend -typecheck -verify -I %t/Cxx/include %t/NoRetroactive.swift -cxx-interoperability-mode=default -module-name Module
5+
6+
//--- Cxx/include/module.modulemap
7+
module CxxModule {
8+
requires cplusplus
9+
header "cxx-header.h"
10+
}
11+
12+
//--- Cxx/include/cxx-header.h
13+
#pragma once
14+
15+
#define SWIFT_PRIVATE_FILEID(_fileID) \
16+
__attribute__((swift_attr("private_fileid:" _fileID)))
17+
18+
class SWIFT_PRIVATE_FILEID("Module/PrivateFile.swift") Foo { void privateMethod(void) const {} };
19+
20+
//--- PrivateFile.swift
21+
import CxxModule
22+
23+
extension Foo : ExpressibleByIntegerLiteral {
24+
public typealias IntegerLiteralType = Int
25+
public init(integerLiteral: Self.IntegerLiteralType) {
26+
self.init()
27+
self.privateMethod()
28+
}
29+
}
30+
31+
//--- HasRetroactive.swift
32+
import CxxModule
33+
34+
extension Foo : @retroactive ExpressibleByIntegerLiteral {
35+
public typealias IntegerLiteralType = Int
36+
public init(integerLiteral: Self.IntegerLiteralType) {
37+
self.init()
38+
self.privateMethod() // expected-error {{'privateMethod' is inaccessible due to 'private' protection level}}
39+
}
40+
}
41+
42+
//--- NoRetroactive.swift
43+
import CxxModule
44+
45+
// expected-warning@+2 {{extension declares a conformance of imported type 'Foo' to imported protocol 'ExpressibleByIntegerLiteral'}}
46+
// expected-note@+1 {{add '@retroactive' to silence this warning}}
47+
extension Foo : ExpressibleByIntegerLiteral {
48+
public typealias IntegerLiteralType = Int
49+
public init(integerLiteral: Self.IntegerLiteralType) {
50+
self.init()
51+
self.privateMethod() // expected-error {{'privateMethod' is inaccessible due to 'private' protection level}}
52+
}
53+
}

0 commit comments

Comments
 (0)