Skip to content

Commit 4a3e94f

Browse files
committed
Gracefully handle incorrect SwiftName arg count
…at least in the specific case of initializers. Normally, clang validates that a SwiftNameAttr’s specified name seems to have the right number of argument labels for the declaration it’s applied to; if it doesn’t, it diagnoses and drops the attribute. However, this checking isn’t perfect because clang doesn’t know all of Clang Importer’s throwing rules. The upshot is that it’s possible to get a mismatched SwiftNameAttr into Clang Importer if the last parameter looks like an out parameter. This trips an assertion in asserts compilers, but release compilers get past that and don’t seem to notice the mismatch at all. Add code to the compiler to tolerate this condition, at least in initializers, by modifying the Swift name to have the correct number of argument labels and deprecating the declaration with a message explaining the problem. Fixes rdar://141124373.
1 parent 3d9dc81 commit 4a3e94f

File tree

3 files changed

+41
-0
lines changed

3 files changed

+41
-0
lines changed

lib/ClangImporter/ImportDecl.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6530,6 +6530,7 @@ Decl *SwiftDeclConverter::importGlobalAsInitializer(
65306530
ArrayRef<Identifier> argNames = name.getArgumentNames();
65316531

65326532
ParameterList *parameterList = nullptr;
6533+
DeclName nameBeforeAdjustment;
65336534
if (argNames.size() == 1 && decl->getNumParams() == 0) {
65346535
// Special case: We need to create an empty first parameter for our
65356536
// argument label
@@ -6545,6 +6546,25 @@ Decl *SwiftDeclConverter::importGlobalAsInitializer(
65456546
parameterList = Impl.importFunctionParameterList(
65466547
dc, decl, {decl->param_begin(), decl->param_end()}, decl->isVariadic(),
65476548
allowNSUIntegerAsInt, argNames, /*genericParams=*/{}, /*resultType=*/nullptr);
6549+
6550+
if (name && parameterList && argNames.size() != parameterList->size()) {
6551+
// Remember that the name has changed.
6552+
nameBeforeAdjustment = name;
6553+
6554+
// Add or remove argument labels as needed to match `parameterList`.
6555+
SmallVector<Identifier, 16> newArgNames;
6556+
llvm::append_range(newArgNames, argNames);
6557+
while (newArgNames.size() > parameterList->size())
6558+
newArgNames.pop_back();
6559+
while (newArgNames.size() < parameterList->size()) {
6560+
auto param = parameterList->get(newArgNames.size());
6561+
newArgNames.push_back(param->getArgumentName());
6562+
}
6563+
6564+
// Construct the new name.
6565+
name = DeclName(Impl.SwiftContext, name.getBaseName(), newArgNames);
6566+
argNames = name.getArgumentNames();
6567+
}
65486568
}
65496569
if (!parameterList)
65506570
return nullptr;
@@ -6582,6 +6602,22 @@ Decl *SwiftDeclConverter::importGlobalAsInitializer(
65826602
result->setIsObjC(false);
65836603
result->setIsDynamic(false);
65846604

6605+
if (nameBeforeAdjustment) {
6606+
SmallString<16> message;
6607+
llvm::raw_svector_ostream os(message);
6608+
os << "declared Swift name '" << nameBeforeAdjustment
6609+
<< "' was adjusted to '" << name
6610+
<< "' because it does not have the correct number of parameters ("
6611+
<< nameBeforeAdjustment.getArgumentNames().size() << " vs. "
6612+
<< name.getArgumentNames().size()
6613+
<< "); please report this to its maintainer";
6614+
6615+
auto attr = AvailableAttr::createPlatformAgnostic(Impl.SwiftContext,
6616+
Impl.SwiftContext.AllocateCopy(message.str()), "",
6617+
PlatformAgnosticAvailabilityKind::Deprecated);
6618+
result->getAttrs().add(attr);
6619+
}
6620+
65856621
finishFuncDecl(decl, result);
65866622
if (correctSwiftName)
65876623
markAsVariant(result, *correctSwiftName);

test/ClangImporter/Inputs/custom-modules/SwiftName.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ typedef int my_int_t SWIFT_NAME(MyInt);
3232
void spuriousAPINotedSwiftName(int);
3333
void poorlyNamedFunction(const char *);
3434

35+
PointType readPoint(const char *path, void **errorOut) SWIFT_NAME(Point.init(path:));
36+
3537
struct BoxForConstants {
3638
int dummy;
3739
};

test/ClangImporter/attr-swift_name_renaming.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ func test() {
2222
var p = Point()
2323
var p2 = PointType() // FIXME: should provide Fix-It expected-error{{cannot find 'PointType' in scope}} {{none}}
2424

25+
// Initializers with incorrect argument count (rdar://141124373)
26+
var p3 = Point(path: "/dev/zero", nil) // expected-warning {{'init(path:_:)' is deprecated: declared Swift name 'init(path:)' was adjusted to 'init(path:_:)' because it does not have the correct number of parameters (1 vs. 2); please report this to its maintainer}}
27+
2528
// Field name remapping
2629
p.x = 7
2730

0 commit comments

Comments
 (0)