Skip to content

Commit 22ec600

Browse files
committed
[Import as Member] Print full context in fixit
Due to swift_name and swift_newtype, we are frequently importing onto different contexts. This was confusing the fixit logic for unavailable swift2 names, as we were trying to use Clang names when the Swift name might be totally different (and even a nested type). This change has a two-fold effect: 1) Globals who are imported onto swift_newtype-ed typedefs should be considered ImportAsMember. 2) When printing out the name of an ImportAsMember Swift 3 decl, we need to print out a fully qualified context, which also uses the Swift names, not the Clang names.
1 parent 6c4acf2 commit 22ec600

File tree

5 files changed

+113
-31
lines changed

5 files changed

+113
-31
lines changed

lib/ClangImporter/ClangImporter.cpp

Lines changed: 47 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1891,12 +1891,48 @@ namespace {
18911891
typedef ClangImporter::Implementation::ImportedName ImportedName;
18921892
}
18931893

1894-
void ClangImporter::Implementation::ImportedName::printSwiftName(
1895-
llvm::raw_ostream &os) const {
1894+
/// Will recursively print out the fully qualified context for the given name.
1895+
/// Ends with a trailing "."
1896+
static void
1897+
printFullContextPrefix(ClangImporter::Implementation::ImportedName name,
1898+
llvm::raw_ostream &os,
1899+
ClangImporter::Implementation &Impl) {
1900+
const clang::NamedDecl *newDeclContextNamed = nullptr;
1901+
switch (name.EffectiveContext.getKind()) {
1902+
case EffectiveClangContext::UnresolvedContext:
1903+
os << name.EffectiveContext.getUnresolvedName() << ".";
1904+
// And we're done!
1905+
return;
1906+
1907+
case EffectiveClangContext::DeclContext: {
1908+
auto namedDecl =
1909+
dyn_cast<clang::NamedDecl>(name.EffectiveContext.getAsDeclContext());
1910+
if (!namedDecl) {
1911+
// We're done
1912+
return;
1913+
}
1914+
newDeclContextNamed = cast<clang::NamedDecl>(namedDecl);
1915+
break;
1916+
}
1917+
1918+
case EffectiveClangContext::TypedefContext:
1919+
newDeclContextNamed = name.EffectiveContext.getTypedefName();
1920+
break;
1921+
}
1922+
1923+
// Now, let's print out the parent
1924+
assert(newDeclContextNamed && "should of been set");
1925+
auto parentName = Impl.importFullName(newDeclContextNamed);
1926+
printFullContextPrefix(parentName, os, Impl);
1927+
os << parentName.Imported << ".";
1928+
}
1929+
1930+
void ClangImporter::Implementation::printSwiftName(ImportedName name,
1931+
llvm::raw_ostream &os) {
18961932
// Property accessors.
18971933
bool isGetter = false;
18981934
bool isSetter = false;
1899-
switch (AccessorKind) {
1935+
switch (name.AccessorKind) {
19001936
case ImportedAccessorKind::None:
19011937
break;
19021938

@@ -1915,43 +1951,27 @@ void ClangImporter::Implementation::ImportedName::printSwiftName(
19151951

19161952
// If we're importing a global as a member, we need to provide the
19171953
// effective context.
1918-
if (ImportAsMember) {
1919-
switch (EffectiveContext.getKind()) {
1920-
case EffectiveClangContext::DeclContext:
1921-
os << SwiftLookupTable::translateDeclContext(
1922-
EffectiveContext.getAsDeclContext())->second;
1923-
break;
1924-
1925-
case EffectiveClangContext::TypedefContext:
1926-
os << EffectiveContext.getTypedefName()->getName();
1927-
break;
1928-
1929-
case EffectiveClangContext::UnresolvedContext:
1930-
os << EffectiveContext.getUnresolvedName();
1931-
break;
1932-
}
1933-
1934-
os << ".";
1935-
}
1954+
if (name.ImportAsMember)
1955+
printFullContextPrefix(name, os, *this);
19361956

19371957
// Base name.
1938-
os << Imported.getBaseName().str();
1958+
os << name.Imported.getBaseName().str();
19391959

19401960
// Determine the number of argument labels we'll be producing.
1941-
auto argumentNames = Imported.getArgumentNames();
1961+
auto argumentNames = name.Imported.getArgumentNames();
19421962
unsigned numArguments = argumentNames.size();
1943-
if (SelfIndex) ++numArguments;
1963+
if (name.SelfIndex) ++numArguments;
19441964
if (isSetter) ++numArguments;
19451965

19461966
// If the result is a simple name that is not a getter, we're done.
1947-
if (numArguments == 0 && Imported.isSimpleName() && !isGetter) return;
1967+
if (numArguments == 0 && name.Imported.isSimpleName() && !isGetter) return;
19481968

19491969
// We need to produce a function name.
19501970
os << "(";
19511971
unsigned currentArgName = 0;
19521972
for (unsigned i = 0; i != numArguments; ++i) {
19531973
// The "self" parameter.
1954-
if (SelfIndex && *SelfIndex == i) {
1974+
if (name.SelfIndex && *name.SelfIndex == i) {
19551975
os << "self:";
19561976
continue;
19571977
}
@@ -2355,6 +2375,7 @@ auto ClangImporter::Implementation::importFullName(
23552375
// Import onto a swift_newtype if present
23562376
} else if (auto newtypeDecl = findSwiftNewtype(D, clangSema, swift2Name)) {
23572377
result.EffectiveContext = newtypeDecl;
2378+
result.ImportAsMember = true;
23582379
// Everything else goes into its redeclaration context.
23592380
} else {
23602381
result.EffectiveContext = dc->getRedeclContext();

lib/ClangImporter/ImportDecl.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1284,14 +1284,15 @@ namespace {
12841284

12851285
/// Mark the given declaration as the Swift 2 variant of a Swift 3
12861286
/// declaration with the given name.
1287-
static void markAsSwift2Variant(Decl *decl, ImportedName swift3Name) {
1287+
void markAsSwift2Variant(Decl *decl, ImportedName swift3Name,
1288+
DeclContext *newDC = nullptr) {
12881289
ASTContext &ctx = decl->getASTContext();
12891290

12901291
llvm::SmallString<64> renamed;
12911292
{
12921293
// Render a swift_name string.
12931294
llvm::raw_svector_ostream os(renamed);
1294-
swift3Name.printSwiftName(os);
1295+
Impl.printSwiftName(swift3Name, os);
12951296
}
12961297

12971298
auto attr = AvailableAttr::createUnconditional(

lib/ClangImporter/ImporterImpl.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -907,9 +907,6 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation
907907
}
908908
}
909909

910-
/// Print this imported name as a string suitable for the swift_name
911-
/// attribute.
912-
void printSwiftName(llvm::raw_ostream &os) const;
913910
};
914911

915912
/// Flags that control the import of names in importFullName.
@@ -938,6 +935,9 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation
938935
const clang::MacroInfo *macro,
939936
clang::ASTContext &clangCtx);
940937

938+
/// Print an imported name as a string suitable for the swift_name attribute.
939+
void printSwiftName(ImportedName, llvm::raw_ostream &os);
940+
941941
/// Retrieve the property type as determined by the given accessor.
942942
static clang::QualType
943943
getAccessorPropertyType(const clang::FunctionDecl *accessor, bool isSetter,

test/IDE/Inputs/custom-modules/Newtype.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,3 +94,11 @@ extern MyABIOldTypeNS getMyABIOldTypeNS(void);
9494
extern void takeMyABINewTypeNonNullNS(__nonnull MyABINewTypeNS);
9595
extern void takeMyABIOldTypeNonNullNS(__nonnull MyABIOldTypeNS);
9696

97+
// Nested types
98+
typedef struct {int i;} NSSomeContext;
99+
100+
typedef NSString *NSSomeContextName __attribute((swift_newtype(struct)))
101+
__attribute((swift_name("NSSomeContext.Name")));
102+
103+
extern const NSSomeContextName NSMyContextName;
104+

test/IDE/newtype.swift

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,52 @@
9191
// PRINT-NEXT: }
9292
// PRINT-NEXT: func FooAudited() -> CFNewType
9393
// PRINT-NEXT: func FooUnaudited() -> Unmanaged<CFString>
94+
//
95+
// PRINT-NEXT: struct MyABINewType : RawRepresentable, _SwiftNewtypeWrapper {
96+
// PRINT-NEXT: init(_ rawValue: CFString)
97+
// PRINT-NEXT: init(rawValue: CFString)
98+
// PRINT-NEXT: let rawValue: CFString
99+
// PRINT-NEXT: }
100+
// PRINT-NEXT: typealias MyABIOldType = CFString
101+
// PRINT-NEXT: extension MyABINewType {
102+
// PRINT-NEXT: static let global: MyABINewType!
103+
// PRINT-NEXT: }
104+
// PRINT-NEXT: let kMyABIOldTypeGlobal: MyABIOldType!
105+
// PRINT-NEXT: func getMyABINewType() -> MyABINewType!
106+
// PRINT-NEXT: func getMyABIOldType() -> MyABIOldType!
107+
// PRINT-NEXT: func takeMyABINewType(_: MyABINewType!)
108+
// PRINT-NEXT: func takeMyABIOldType(_: MyABIOldType!)
109+
// PRINT-NEXT: func takeMyABINewTypeNonNull(_: MyABINewType)
110+
// PRINT-NEXT: func takeMyABIOldTypeNonNull(_: MyABIOldType)
111+
// PRINT-NEXT: struct MyABINewTypeNS : RawRepresentable, _SwiftNewtypeWrapper, Equatable, Hashable, Comparable, _ObjectiveCBridgeable {
112+
// PRINT-NEXT: init(_ rawValue: String)
113+
// PRINT-NEXT: init(rawValue: String)
114+
// PRINT-NEXT: var _rawValue: NSString
115+
// PRINT-NEXT: var rawValue: String { get }
116+
// PRINT-NEXT: }
117+
// PRINT-NEXT: typealias MyABIOldTypeNS = NSString
118+
// PRINT-NEXT: func getMyABINewTypeNS() -> MyABINewTypeNS!
119+
// PRINT-NEXT: func getMyABIOldTypeNS() -> String!
120+
// PRINT-NEXT: func takeMyABINewTypeNonNullNS(_: MyABINewTypeNS)
121+
// PRINT-NEXT: func takeMyABIOldTypeNonNullNS(_: String)
122+
//
123+
// PRINT-NEXT: struct NSSomeContext {
124+
// PRINT-NEXT: var i: Int32
125+
// PRINT-NEXT: init()
126+
// PRINT-NEXT: init(i: Int32)
127+
// PRINT-NEXT: }
128+
// PRINT-NEXT: extension NSSomeContext {
129+
// PRINT-NEXT: struct Name : RawRepresentable, _SwiftNewtypeWrapper, Equatable, Hashable, Comparable, _ObjectiveCBridgeable {
130+
// PRINT-NEXT: init(_ rawValue: String)
131+
// PRINT-NEXT: init(rawValue: String)
132+
// PRINT-NEXT: var _rawValue: NSString
133+
// PRINT-NEXT: var rawValue: String { get }
134+
// PRINT-NEXT: }
135+
// PRINT-NEXT: }
136+
// PRINT-NEXT: extension NSSomeContext.Name {
137+
// PRINT-NEXT: static let myContextName: NSSomeContext.Name
138+
// PRINT-NEXT: }
139+
94140
import Newtype
95141

96142
func tests() {
@@ -129,3 +175,9 @@ func testConformances(ed: ErrorDomain) {
129175
acceptComparable(ed)
130176
acceptObjectiveCBridgeable(ed)
131177
}
178+
179+
func testFixit() {
180+
let _ = NSMyContextName
181+
// expected-error@-1{{'NSMyContextName' has been renamed to 'NSSomeContext.Name.myContextName'}}
182+
183+
}

0 commit comments

Comments
 (0)