Skip to content

[WIP] Testing more multi name import stuff #7749

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions include/swift/ClangImporter/ClangImporter.h
Original file line number Diff line number Diff line change
Expand Up @@ -260,8 +260,7 @@ class ClangImporter final : public ClangModuleLoader {
/// The return value may be an empty identifier, in which case the enum would
/// not be imported.
///
/// This is mostly an implementation detail of the importer, but is also
/// used by the debugger.
/// This is not used by the importer itself, but is used by the debugger.
Identifier getEnumConstantName(const clang::EnumConstantDecl *enumConstant);

/// Writes the mangled name of \p clangDecl to \p os.
Expand Down
48 changes: 41 additions & 7 deletions lib/ClangImporter/ClangImporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2738,17 +2738,51 @@ void ClangImporter::Implementation::lookupValue(
}
}

// If we have a declaration and nothing matched so far, try the Swift 2
// name.
// If we have a declaration and nothing matched so far, try the names used
// in other versions of Swift.
if (!anyMatching) {
if (auto clangDecl = entry.dyn_cast<clang::NamedDecl *>()) {
if (auto swift2Decl = cast_or_null<ValueDecl>(importDeclReal(
clangDecl->getMostRecentDecl(), ImportNameVersion::Swift2))) {
if (swift2Decl->getFullName().matchesRef(name) &&
swift2Decl->getDeclContext()->isModuleScopeContext()) {
consumer.foundDecl(swift2Decl,
const clang::NamedDecl *recentClangDecl =
clangDecl->getMostRecentDecl();
auto tryImport = [&](ImportNameVersion nameVersion) -> bool {
// Check to see if the name and context match what we expect.
ImportedName newName = importFullName(recentClangDecl, nameVersion);
if (!newName.getDeclName().matchesRef(name))
return false;

const clang::DeclContext *clangDC =
newName.getEffectiveContext().getAsDeclContext();
if (!clangDC || !clangDC->isFileContext())
return false;

// Then try to import the decl under the alternate name.
auto alternateNamedDecl =
cast_or_null<ValueDecl>(importDeclReal(recentClangDecl,
nameVersion));
if (!alternateNamedDecl)
return false;
assert(alternateNamedDecl->getFullName().matchesRef(name) &&
"importFullName behaved differently from importDecl");
if (alternateNamedDecl->getDeclContext()->isModuleScopeContext()) {
consumer.foundDecl(alternateNamedDecl,
DeclVisibilityKind::VisibleAtTopLevel);
return true;
}
return false;
};

// Try importing previous versions of the decl first...
ImportNameVersion nameVersion = CurrentVersion;
while (!anyMatching && nameVersion != ImportNameVersion::Raw) {
--nameVersion;
anyMatching = tryImport(nameVersion);
}
// ...then move on to newer versions if none of the old versions
// matched.
nameVersion = CurrentVersion;
while (!anyMatching && nameVersion != ImportNameVersion::LAST_VERSION) {
++nameVersion;
anyMatching = tryImport(nameVersion);
}
}
}
Expand Down
113 changes: 60 additions & 53 deletions lib/ClangImporter/ImportDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2009,18 +2009,43 @@ namespace {
/*fullyQualified=*/correctSwiftName.importAsMember(), os);
}

auto attr = AvailableAttr::createPlatformAgnostic(
ctx, StringRef(), ctx.AllocateCopy(renamed.str()),
PlatformAgnosticAvailabilityKind::SwiftVersionSpecific,
clang::VersionTuple(3));
unsigned majorVersion = majorVersionNumberForNameVersion(getVersion());
DeclAttribute *attr;
if (isActiveSwiftVersion() || getVersion() == ImportNameVersion::Raw) {
// "Raw" is the Objective-C name, which was never available in Swift.
// Variants within the active version are usually declarations that
// have been superseded, like the accessors of a property.
attr = AvailableAttr::createPlatformAgnostic(
ctx, /*Message*/StringRef(), ctx.AllocateCopy(renamed.str()),
PlatformAgnosticAvailabilityKind::UnavailableInSwift);
} else if (getVersion() < getActiveSwiftVersion()) {
// A Swift 2 name, for example, was obsoleted in Swift 3.
attr = AvailableAttr::createPlatformAgnostic(
ctx, /*Message*/StringRef(), ctx.AllocateCopy(renamed.str()),
PlatformAgnosticAvailabilityKind::SwiftVersionSpecific,
clang::VersionTuple(majorVersion + 1));
} else {
// Future names are introduced in their future version.
assert(getVersion() > getActiveSwiftVersion());
attr = new (ctx) AvailableAttr(
SourceLoc(), SourceRange(), PlatformKind::none,
/*Message*/StringRef(), ctx.AllocateCopy(renamed.str()),
/*Introduced*/clang::VersionTuple(majorVersion), SourceRange(),
/*Deprecated*/clang::VersionTuple(), SourceRange(),
/*Obsoleted*/clang::VersionTuple(), SourceRange(),
PlatformAgnosticAvailabilityKind::SwiftVersionSpecific,
/*Implicit*/true);
}

decl->getAttrs().add(attr);
decl->setImplicit();
}

/// Create a typealias for the Swift 2 name of a Clang type declaration.
Decl *importSwift2TypeAlias(const clang::NamedDecl *decl,
ImportedName swift2Name,
ImportedName correctSwiftName);
/// Create a typealias for the name of a Clang type declaration in an
/// alternate version of Swift.
Decl *importCompatibilityTypeAlias(const clang::NamedDecl *decl,
ImportedName compatibilityName,
ImportedName correctSwiftName);

/// Create a swift_newtype struct corresponding to a typedef. Returns
/// nullptr if unable.
Expand All @@ -2038,7 +2063,8 @@ namespace {
// If we've been asked to produce a Swift 2 stub, handle it via a
// typealias.
if (correctSwiftName)
return importSwift2TypeAlias(Decl, importedName, *correctSwiftName);
return importCompatibilityTypeAlias(Decl, importedName,
*correctSwiftName);

Type SwiftType;
if (Decl->getDeclContext()->getRedeclContext()->isTranslationUnit()) {
Expand Down Expand Up @@ -2253,7 +2279,8 @@ namespace {
// If we've been asked to produce a Swift 2 stub, handle it via a
// typealias.
if (correctSwiftName)
return importSwift2TypeAlias(decl, importedName, *correctSwiftName);
return importCompatibilityTypeAlias(decl, importedName,
*correctSwiftName);

auto dc =
Impl.importDeclContextOf(decl, importedName.getEffectiveContext());
Expand Down Expand Up @@ -2669,7 +2696,8 @@ namespace {
// If we've been asked to produce a Swift 2 stub, handle it via a
// typealias.
if (correctSwiftName)
return importSwift2TypeAlias(decl, importedName, *correctSwiftName);
return importCompatibilityTypeAlias(decl, importedName,
*correctSwiftName);

auto dc =
Impl.importDeclContextOf(decl, importedName.getEffectiveContext());
Expand Down Expand Up @@ -3485,31 +3513,12 @@ namespace {
{decl->param_begin(), decl->param_size()},
decl->isVariadic(), redundant);

// Directly ask the NameImporter for the non-init variant of the Swift 2
// name.
auto rawName = Impl.importFullName(decl, ImportNameVersion::Raw);
if (!rawName)
return result;

auto rawDecl = importNonInitObjCMethodDecl(decl, dc, rawName, selector,
forceClassMethod);
if (!rawDecl)
return result;

// Mark the raw imported class method "unavailable", with a useful error
// message.
llvm::SmallString<64> message;
llvm::raw_svector_ostream os(message);
os << "use object construction '" << decl->getClassInterface()->getName()
<< "(";
for (auto arg : importedName.getDeclName().getArgumentNames()) {
os << arg << ":";
if (auto rawDecl = Impl.importDecl(decl, ImportNameVersion::Raw)) {
// We expect the raw decl to always be a method.
assert(isa<FuncDecl>(rawDecl));
Impl.addAlternateDecl(result, cast<ValueDecl>(rawDecl));
}
os << ")'";
rawDecl->getAttrs().add(AvailableAttr::createPlatformAgnostic(
Impl.SwiftContext, Impl.SwiftContext.AllocateCopy(os.str())));
markAsVariant(rawDecl, importedName);
Impl.addAlternateDecl(result, cast<ValueDecl>(rawDecl));

return result;
}

Expand Down Expand Up @@ -3952,7 +3961,8 @@ namespace {
// If we've been asked to produce a Swift 2 stub, handle it via a
// typealias.
if (correctSwiftName)
return importSwift2TypeAlias(decl, importedName, *correctSwiftName);
return importCompatibilityTypeAlias(decl, importedName,
*correctSwiftName);

Identifier name = importedName.getDeclName().getBaseName();

Expand Down Expand Up @@ -4087,7 +4097,8 @@ namespace {
// If we've been asked to produce a Swift 2 stub, handle it via a
// typealias.
if (correctSwiftName)
return importSwift2TypeAlias(decl, importedName, *correctSwiftName);
return importCompatibilityTypeAlias(decl, importedName,
*correctSwiftName);

auto name = importedName.getDeclName().getBaseName();

Expand Down Expand Up @@ -4625,9 +4636,10 @@ SwiftDeclConverter::importCFClassType(const clang::TypedefNameDecl *decl,
return theClass;
}

Decl *SwiftDeclConverter::importSwift2TypeAlias(const clang::NamedDecl *decl,
ImportedName swift2Name,
ImportedName correctSwiftName) {
Decl *SwiftDeclConverter::importCompatibilityTypeAlias(
const clang::NamedDecl *decl,
ImportedName compatibilityName,
ImportedName correctSwiftName) {
// Import the referenced declaration. If it doesn't come in as a type,
// we don't care.
auto importedDecl = Impl.importDecl(decl, getActiveSwiftVersion());
Expand Down Expand Up @@ -4660,19 +4672,14 @@ Decl *SwiftDeclConverter::importSwift2TypeAlias(const clang::NamedDecl *decl,

// Create the type alias.
auto alias = Impl.createDeclWithClangNode<TypeAliasDecl>(
decl,
Accessibility::Public, Impl.importSourceLoc(decl->getLocStart()),
SourceLoc(), swift2Name.getDeclName().getBaseName(),
Impl.importSourceLoc(decl->getLocation()),
genericParams, dc);
decl, Accessibility::Public, Impl.importSourceLoc(decl->getLocStart()),
SourceLoc(), compatibilityName.getDeclName().getBaseName(),
Impl.importSourceLoc(decl->getLocation()), genericParams, dc);
alias->setUnderlyingType(underlyingType);
alias->setGenericEnvironment(genericEnv);

// Record that this is the Swift 2 version of this declaration.
Impl.ImportedDecls[{decl->getCanonicalDecl(), ImportNameVersion::Swift2}] =
alias;

// Mark it as the Swift 2 variant.
// Record that this is the official version of this declaration.
Impl.ImportedDecls[{decl->getCanonicalDecl(), getVersion()}] = alias;
markAsVariant(alias, correctSwiftName);
return alias;
}
Expand Down Expand Up @@ -6511,7 +6518,7 @@ getSwiftNameFromClangName(StringRef replacement) {
if (!clangDecl)
return "";

auto importedName = importFullName(clangDecl, ImportNameVersion::Swift3);
auto importedName = importFullName(clangDecl, CurrentVersion);
if (!importedName)
return "";

Expand Down Expand Up @@ -6753,7 +6760,7 @@ ClangImporter::Implementation::importDeclImpl(const clang::NamedDecl *ClangDecl,
Result = converter.Visit(ClangDecl);
HadForwardDeclaration = converter.hadForwardDeclaration();
}
if (!Result && version > ImportNameVersion::Swift2) {
if (!Result && version == CurrentVersion) {
// If we couldn't import this Objective-C entity, determine
// whether it was a required member of a protocol.
bool hasMissingRequiredMember = false;
Expand Down Expand Up @@ -7563,7 +7570,7 @@ ClangImporter::Implementation::getSpecialTypedefKind(clang::TypedefNameDecl *dec

Identifier
ClangImporter::getEnumConstantName(const clang::EnumConstantDecl *enumConstant){
return Impl.importFullName(enumConstant, ImportNameVersion::Swift3)
return Impl.importFullName(enumConstant, Impl.CurrentVersion)
.getDeclName()
.getBaseName();
}
Expand Down
Loading