Skip to content

Commit 0d3ef54

Browse files
committed
ClangImporter: Add support for __attribute__((availability(..., replacement="")))
We map clang::AvailabilityAttr::getReplacement() to swift::AvailableAttr::Rename, transforming the replacement name using by looking up the named Clang replacement, and importing its name. Fixes <rdar://problem/26301742>.
1 parent 609b244 commit 0d3ef54

File tree

5 files changed

+75
-12
lines changed

5 files changed

+75
-12
lines changed

lib/ClangImporter/ClangImporter.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1928,6 +1928,7 @@ printFullContextPrefix(ClangImporter::Implementation::ImportedName name,
19281928
}
19291929

19301930
void ClangImporter::Implementation::printSwiftName(ImportedName name,
1931+
bool fullyQualified,
19311932
llvm::raw_ostream &os) {
19321933
// Property accessors.
19331934
bool isGetter = false;
@@ -1949,9 +1950,7 @@ void ClangImporter::Implementation::printSwiftName(ImportedName name,
19491950
break;
19501951
}
19511952

1952-
// If we're importing a global as a member, we need to provide the
1953-
// effective context.
1954-
if (name.ImportAsMember)
1953+
if (fullyQualified)
19551954
printFullContextPrefix(name, os, *this);
19561955

19571956
// Base name.

lib/ClangImporter/ImportDecl.cpp

Lines changed: 54 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1292,7 +1292,12 @@ namespace {
12921292
{
12931293
// Render a swift_name string.
12941294
llvm::raw_svector_ostream os(renamed);
1295-
Impl.printSwiftName(swift3Name, os);
1295+
1296+
// If we're importing a global as a member, we need to provide the
1297+
// effective context.
1298+
Impl.printSwiftName(swift3Name,
1299+
/*fullyQualified=*/swift3Name.ImportAsMember,
1300+
os);
12961301
}
12971302

12981303
auto attr = AvailableAttr::createUnconditional(
@@ -6093,6 +6098,38 @@ clang::SwiftNewtypeAttr *ClangImporter::Implementation::getSwiftNewtypeAttr(
60936098
return decl->getAttr<clang::SwiftNewtypeAttr>();
60946099
}
60956100

6101+
StringRef ClangImporter::Implementation::
6102+
getSwiftNameFromClangName(StringRef replacement) {
6103+
auto &clangSema = getClangSema();
6104+
6105+
clang::IdentifierInfo *identifier =
6106+
&clangSema.getASTContext().Idents.get(replacement);
6107+
clang::LookupResult lookupResult(clangSema, identifier,
6108+
clang::SourceLocation(),
6109+
clang::Sema::LookupOrdinaryName);
6110+
if (!clangSema.LookupName(lookupResult, nullptr))
6111+
return "";
6112+
6113+
auto clangDecl = lookupResult.getAsSingle<clang::NamedDecl>();
6114+
if (!clangDecl)
6115+
return "";
6116+
6117+
auto importedName = importFullName(clangDecl, None, &clangSema);
6118+
if (!importedName)
6119+
return "";
6120+
6121+
llvm::SmallString<64> renamed;
6122+
{
6123+
// Render a swift_name string.
6124+
llvm::raw_svector_ostream os(renamed);
6125+
printSwiftName(importedName,
6126+
/*fullyQualified=*/true,
6127+
os);
6128+
}
6129+
6130+
return SwiftContext.AllocateCopy(StringRef(renamed));
6131+
}
6132+
60966133
/// Import Clang attributes as Swift attributes.
60976134
void ClangImporter::Implementation::importAttributes(
60986135
const clang::NamedDecl *ClangDecl,
@@ -6111,7 +6148,7 @@ void ClangImporter::Implementation::importAttributes(
61116148
for (clang::NamedDecl::attr_iterator AI = ClangDecl->attr_begin(),
61126149
AE = ClangDecl->attr_end(); AI != AE; ++AI) {
61136150
//
6114-
// __attribute__((unavailable)
6151+
// __attribute__((unavailable))
61156152
//
61166153
// Mapping: @available(*,unavailable)
61176154
//
@@ -6157,8 +6194,13 @@ void ClangImporter::Implementation::importAttributes(
61576194

61586195
// Is this our special "availability(swift, unavailable)" attribute?
61596196
if (Platform == "swift") {
6197+
auto replacement = avail->getReplacement();
6198+
StringRef swiftReplacement = "";
6199+
if (!replacement.empty())
6200+
swiftReplacement = getSwiftNameFromClangName(replacement);
6201+
61606202
auto attr = AvailableAttr::createUnconditional(
6161-
C, avail->getMessage(), /*renamed*/"",
6203+
C, avail->getMessage(), swiftReplacement,
61626204
UnconditionalAvailabilityKind::UnavailableInSwift);
61636205
MappedDecl->getAttrs().add(attr);
61646206
AnyUnavailable = true;
@@ -6211,12 +6253,17 @@ void ClangImporter::Implementation::importAttributes(
62116253

62126254
const auto &obsoleted = avail->getObsoleted();
62136255
const auto &introduced = avail->getIntroduced();
6256+
const auto &replacement = avail->getReplacement();
6257+
6258+
StringRef swiftReplacement = "";
6259+
if (!replacement.empty())
6260+
swiftReplacement = getSwiftNameFromClangName(replacement);
62146261

62156262
auto AvAttr = new (C) AvailableAttr(SourceLoc(), SourceRange(),
6216-
platformK.getValue(),
6217-
message, /*rename*/StringRef(),
6218-
introduced, deprecated, obsoleted,
6219-
Unconditional, /*implicit=*/false);
6263+
platformK.getValue(),
6264+
message, swiftReplacement,
6265+
introduced, deprecated, obsoleted,
6266+
Unconditional, /*implicit=*/false);
62206267

62216268
MappedDecl->getAttrs().add(AvAttr);
62226269
}

lib/ClangImporter/ImporterImpl.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -935,8 +935,9 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation
935935
const clang::MacroInfo *macro,
936936
clang::ASTContext &clangCtx);
937937

938-
/// Print an imported name as a string suitable for the swift_name attribute.
939-
void printSwiftName(ImportedName, llvm::raw_ostream &os);
938+
/// Print an imported name as a string suitable for the swift_name attribute,
939+
/// or the 'Rename' field of AvailableAttr.
940+
void printSwiftName(ImportedName, bool fullyQualified, llvm::raw_ostream &os);
940941

941942
/// Retrieve the property type as determined by the given accessor.
942943
static clang::QualType
@@ -982,6 +983,9 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation
982983
const clang::TypedefNameDecl *decl,
983984
bool useSwift2Name);
984985

986+
/// Map a Clang identifier name to its imported Swift equivalent.
987+
StringRef getSwiftNameFromClangName(StringRef name);
988+
985989
/// Import attributes from the given Clang declaration to its Swift
986990
/// equivalent.
987991
///

test/ClangModules/availability.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,3 +115,8 @@ func testImportAsMember() {
115115
_ = CGColorCreateGenericGray(0.5, 1.0) // expected-error {{'CGColorCreateGenericGray' has been replaced by 'CGColor.init(gray:alpha:)'}} {{7-31=CGColor}} {{32-32=gray: }} {{37-37=alpha: }}
116116
_ = CGColor(gray: 0.5, alpha: 1.0)
117117
}
118+
119+
func testUnavailableRenamedEnum() {
120+
_ = NSClothingStyle.hipster
121+
_ = NSClothingStyleOfficeCasual // expected-error{{'NSClothingStyleOfficeCasual' has been renamed to 'NSClothingStyle.semiFormal'}} {{7-34=NSClothingStyle.semiFormal}}
122+
}

test/Inputs/clang-importer-sdk/usr/include/Foundation.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1021,3 +1021,11 @@ extern NSString *NSHTTPRequestKey;
10211021

10221022
#define NSTimeIntervalSince1970 978307200.0
10231023
#define NS_DO_SOMETHING 17
1024+
1025+
typedef NS_ENUM(NSUInteger, NSClothingStyle) {
1026+
NSClothingStyleFormal = 0,
1027+
NSClothingStyleSemiFormal,
1028+
NSClothingStyleHipster,
1029+
NSClothingStyleHippie
1030+
};
1031+
static const NSClothingStyle NSClothingStyleOfficeCasual __attribute__((availability(swift,unavailable,replacement="NSClothingStyleSemiFormal"))) = NSClothingStyleSemiFormal;

0 commit comments

Comments
 (0)