Skip to content

Commit cb8dbd9

Browse files
authored
[ClangImporter] Import builtins returning size_t as returning Int. (#9753)
...which is consistent with other library functions return size_t. But don't break compatibility with Swift 3. ("Builtins" are functions that Clang has, well, built-in knowledge about, and whose declarations can therefore be produced directly in the compiler. This bypassed some of our checking for special typedefs like size_t. We discovered this when 'wcslen' got added as a new built-in in the Swift 4 timeframe.) rdar://problem/30545505
1 parent 96a1ab7 commit cb8dbd9

File tree

3 files changed

+72
-0
lines changed

3 files changed

+72
-0
lines changed

lib/ClangImporter/ImportType.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1540,6 +1540,34 @@ Type ClangImporter::Implementation::importFunctionReturnType(
15401540
DeclContext *dc,
15411541
const clang::FunctionDecl *clangDecl,
15421542
bool allowNSUIntegerAsInt) {
1543+
1544+
// Hardcode handling of certain result types for builtins.
1545+
auto builtinID = clangDecl->getBuiltinID();
1546+
switch (builtinID) {
1547+
case clang::Builtin::NotBuiltin:
1548+
break;
1549+
case clang::Builtin::BIstrxfrm:
1550+
case clang::Builtin::BIstrcspn:
1551+
case clang::Builtin::BIstrspn:
1552+
case clang::Builtin::BIstrlen:
1553+
case clang::Builtin::BIstrlcpy:
1554+
case clang::Builtin::BIstrlcat:
1555+
// This is a list of all built-ins with a result type of 'size_t' that
1556+
// existed in Swift 3. We didn't have special handling for builtins at
1557+
// that time, and so these had a result type of UInt.
1558+
if (SwiftContext.isSwiftVersion3())
1559+
break;
1560+
LLVM_FALLTHROUGH;
1561+
default:
1562+
switch (getClangASTContext().BuiltinInfo.getTypeString(builtinID)[0]) {
1563+
case 'z': // size_t
1564+
case 'Y': // ptrdiff_t
1565+
return SwiftContext.getIntDecl()->getDeclaredType();
1566+
default:
1567+
break;
1568+
}
1569+
}
1570+
15431571
// CF function results can be managed if they are audited or
15441572
// the ownership convention is explicitly declared.
15451573
assert(clangDecl && "expected to have a decl to import");
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// RUN: not %target-swift-frontend -swift-version 3 -typecheck %s 2>&1 | %FileCheck -check-prefix=CHECK-3 -check-prefix=CHECK-%target-runtime-3 %s
2+
// RUN: not %target-swift-frontend -swift-version 4 -typecheck %s 2>&1 | %FileCheck -check-prefix=CHECK-4 -check-prefix=CHECK-%target-runtime-4 %s
3+
4+
#if os(OSX) || os(iOS) || os(watchOS) || os(tvOS)
5+
import Darwin
6+
#else
7+
import Glibc
8+
#endif
9+
10+
func test() {
11+
let _: Int = strxfrm
12+
// CHECK-3: [[@LINE-1]]:16: error: cannot convert value of type '({{.+}}) -> UInt'{{( [(]aka .+[)])?}} to specified type 'Int'
13+
// CHECK-4: [[@LINE-2]]:16: error: cannot convert value of type '({{.+}}) -> Int'{{( [(]aka .+[)])?}} to specified type 'Int'
14+
15+
let _: Int = strcspn
16+
// CHECK-3: [[@LINE-1]]:16: error: cannot convert value of type '({{.+}}) -> UInt'{{( [(]aka .+[)])?}} to specified type 'Int'
17+
// CHECK-4: [[@LINE-2]]:16: error: cannot convert value of type '({{.+}}) -> Int'{{( [(]aka .+[)])?}} to specified type 'Int'
18+
19+
let _: Int = strspn
20+
// CHECK-3: [[@LINE-1]]:16: error: cannot convert value of type '({{.+}}) -> UInt'{{( [(]aka .+[)])?}} to specified type 'Int'
21+
// CHECK-4: [[@LINE-2]]:16: error: cannot convert value of type '({{.+}}) -> Int'{{( [(]aka .+[)])?}} to specified type 'Int'
22+
23+
let _: Int = strlen
24+
// CHECK-3: [[@LINE-1]]:16: error: cannot convert value of type '({{.+}}) -> UInt'{{( [(]aka .+[)])?}} to specified type 'Int'
25+
// CHECK-4: [[@LINE-2]]:16: error: cannot convert value of type '({{.+}}) -> Int'{{( [(]aka .+[)])?}} to specified type 'Int'
26+
}
27+
28+
// These functions aren't consistently available across platforms, so only
29+
// test for them on Apple platforms.
30+
func testApple() {
31+
let _: Int = strlcpy
32+
// CHECK-objc-3: [[@LINE-1]]:16: error: cannot convert value of type '({{.+}}) -> UInt'{{( [(]aka .+[)])?}} to specified type 'Int'
33+
// CHECK-objc-4: [[@LINE-2]]:16: error: cannot convert value of type '({{.+}}) -> Int'{{( [(]aka .+[)])?}} to specified type 'Int'
34+
35+
let _: Int = strlcat
36+
// CHECK-objc-3: [[@LINE-1]]:16: error: cannot convert value of type '({{.+}}) -> UInt'{{( [(]aka .+[)])?}} to specified type 'Int'
37+
// CHECK-objc-4: [[@LINE-2]]:16: error: cannot convert value of type '({{.+}}) -> Int'{{( [(]aka .+[)])?}} to specified type 'Int'
38+
39+
// wcslen is different: it wasn't a builtin until Swift 4, and so its return
40+
// type has always been 'Int'.
41+
let _: Int = wcslen
42+
// CHECK-objc-3: [[@LINE-1]]:16: error: cannot convert value of type '({{.+}}) -> Int'{{( [(]aka .+[)])?}} to specified type 'Int'
43+
// CHECK-objc-4: [[@LINE-2]]:16: error: cannot convert value of type '({{.+}}) -> Int'{{( [(]aka .+[)])?}} to specified type 'Int'
44+
}

0 commit comments

Comments
 (0)