Skip to content

Commit 544b4e8

Browse files
committed
[ClangImporter] C static-qualified array params are non-nullable.
If the keyword 'static' also appears within the '[' and ']' of the array type derivation, then for each call to the function, the value of the corresponding actual argument shall provide access to the first element of an array with at least as many elements as specified by the size expression. (C11 6.7.6.3p7) Limit this change to Swift 4 so as not to break existing code, though use of 'static' in this way is rare to begin with and passing nil would probably be an error anyway. Small part of rdar://problem/25846421.
1 parent 290c745 commit 544b4e8

File tree

7 files changed

+41
-7
lines changed

7 files changed

+41
-7
lines changed

lib/ClangImporter/ClangAdapter.cpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -695,19 +695,28 @@ bool importer::isUnavailableInSwift(
695695
return false;
696696
}
697697

698-
OptionalTypeKind importer::getParamOptionality(const clang::ParmVarDecl *param,
698+
OptionalTypeKind importer::getParamOptionality(version::Version swiftVersion,
699+
const clang::ParmVarDecl *param,
699700
bool knownNonNull) {
700701
auto &clangCtx = param->getASTContext();
701702

702703
// If nullability is available on the type, use it.
703-
if (auto nullability = param->getType()->getNullability(clangCtx)) {
704+
clang::QualType paramTy = param->getType();
705+
if (auto nullability = paramTy->getNullability(clangCtx)) {
704706
return translateNullability(*nullability);
705707
}
706708

707709
// If it's known non-null, use that.
708710
if (knownNonNull || param->hasAttr<clang::NonNullAttr>())
709711
return OTK_None;
710712

713+
// Check for the 'static' annotation on C arrays.
714+
if (!swiftVersion.isVersion3())
715+
if (const auto *DT = dyn_cast<clang::DecayedType>(paramTy))
716+
if (const auto *AT = DT->getOriginalType()->getAsArrayTypeUnsafe())
717+
if (AT->getSizeModifier() == clang::ArrayType::Static)
718+
return OTK_None;
719+
711720
// Default to implicitly unwrapped optionals.
712721
return OTK_ImplicitlyUnwrappedOptional;
713722
}

lib/ClangImporter/ClangAdapter.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,11 +139,15 @@ bool isUnavailableInSwift(const clang::Decl *decl, const PlatformAvailability &,
139139

140140
/// Determine the optionality of the given Clang parameter.
141141
///
142+
/// \param swiftLanguageVersion What version of Swift we're using, which affects
143+
/// how optionality is inferred.
144+
///
142145
/// \param param The Clang parameter.
143146
///
144147
/// \param knownNonNull Whether a function- or method-level "nonnull" attribute
145148
/// applies to this parameter.
146-
OptionalTypeKind getParamOptionality(const clang::ParmVarDecl *param,
149+
OptionalTypeKind getParamOptionality(version::Version swiftLanguageVersion,
150+
const clang::ParmVarDecl *param,
147151
bool knownNonNull);
148152
}
149153
}

lib/ClangImporter/ImportName.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -713,6 +713,8 @@ static bool omitNeedlessWordsInFunctionName(
713713
Optional<unsigned> errorParamIndex, bool returnsSelf, bool isInstanceMethod,
714714
NameImporter &nameImporter) {
715715
clang::ASTContext &clangCtx = nameImporter.getClangContext();
716+
const version::Version &swiftLanguageVersion =
717+
nameImporter.getLangOpts().EffectiveLanguageVersion;
716718

717719
// Collect the parameter type names.
718720
StringRef firstParamName;
@@ -741,7 +743,8 @@ static bool omitNeedlessWordsInFunctionName(
741743
bool hasDefaultArg =
742744
ClangImporter::Implementation::inferDefaultArgument(
743745
param->getType(),
744-
getParamOptionality(param, !nonNullArgs.empty() && nonNullArgs[i]),
746+
getParamOptionality(swiftLanguageVersion, param,
747+
!nonNullArgs.empty() && nonNullArgs[i]),
745748
nameImporter.getIdentifier(baseName), numParams, argumentName,
746749
i == 0, isLastParameter, nameImporter) != DefaultArgumentKind::None;
747750

lib/ClangImporter/ImportType.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1550,7 +1550,8 @@ ParameterList *ClangImporter::Implementation::importFunctionParameterList(
15501550

15511551
// Check nullability of the parameter.
15521552
OptionalTypeKind OptionalityOfParam =
1553-
getParamOptionality(param, !nonNullArgs.empty() && nonNullArgs[index]);
1553+
getParamOptionality(SwiftContext.LangOpts.EffectiveLanguageVersion,
1554+
param, !nonNullArgs.empty() && nonNullArgs[index]);
15541555

15551556
ImportTypeKind importKind = ImportTypeKind::Parameter;
15561557
if (param->hasAttr<clang::CFReturnsRetainedAttr>())
@@ -1933,8 +1934,9 @@ Type ClangImporter::Implementation::importMethodType(
19331934

19341935
// Check nullability of the parameter.
19351936
OptionalTypeKind optionalityOfParam
1936-
= getParamOptionality(param,
1937-
!nonNullArgs.empty() && nonNullArgs[paramIndex]);
1937+
= getParamOptionality(SwiftContext.LangOpts.EffectiveLanguageVersion,
1938+
param,
1939+
!nonNullArgs.empty() && nonNullArgs[paramIndex]);
19381940

19391941
bool allowNSUIntegerAsIntInParam = isFromSystemModule;
19401942
if (allowNSUIntegerAsIntInParam) {

test/ClangImporter/ctypes_parse.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,4 +222,9 @@ func testArrays() {
222222

223223
nullableArrayParameters([], [], [])
224224
nullableArrayParameters(nil, nil, nil)
225+
226+
// It would also be nice to warn here about the arrays being too short, but
227+
// that's probably beyond us for a while.
228+
staticBoundsArray([])
229+
staticBoundsArray(nil) // no-error
225230
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// RUN: %target-parse-verify-swift %clang-importer-sdk -swift-version 4
2+
3+
import ctypes
4+
5+
func testArrays() {
6+
// It would also be nice to warn here about the arrays being too short, but
7+
// that's probably beyond us for a while.
8+
staticBoundsArray([])
9+
staticBoundsArray(nil) // expected-error {{nil is not compatible with expected argument type 'UnsafePointer<Int8>'}}
10+
}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,7 @@ typedef struct ModRM {
265265
// Arrays
266266
//===---
267267
void useArray(char x[4], char y[], char z[][8]);
268+
void staticBoundsArray(const char x[static 4]);
268269

269270
typedef const int FourConstInts[4];
270271
void nonnullArrayParameters(const char x[_Nonnull], void * const _Nullable y[_Nonnull], _Nonnull FourConstInts z);

0 commit comments

Comments
 (0)