mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[ClangImporter] Avoid trying to import enums without definitions. (#11394)
This would fail later down the line anyway, meaning this does not
change the ultimate behavior of the importer, but since I added an
assertion that we're expecting a definition here in 2c68f8d49d, we
need to avoid even asking the question.
Also fix up a few other places where we aren't sure we'll have a
definition when calling these functions.
rdar://problem/33784466
This commit is contained in:
@@ -36,6 +36,9 @@ using namespace importer;
|
||||
/// Classify the given Clang enumeration to describe how to import it.
|
||||
void EnumInfo::classifyEnum(ASTContext &ctx, const clang::EnumDecl *decl,
|
||||
clang::Preprocessor &pp) {
|
||||
assert(decl);
|
||||
clang::PrettyStackTraceDecl trace(decl, clang::SourceLocation(),
|
||||
pp.getSourceManager(), "classifying");
|
||||
assert(decl->isThisDeclarationADefinition());
|
||||
|
||||
// Anonymous enumerations simply get mapped to constants of the
|
||||
|
||||
@@ -1545,11 +1545,13 @@ ImportedName NameImporter::importNameImpl(const clang::NamedDecl *D,
|
||||
// "Code" off the end of the name, if it's there, because it's
|
||||
// redundant.
|
||||
if (auto enumDecl = dyn_cast<clang::EnumDecl>(D)) {
|
||||
if (enumDecl->isThisDeclarationADefinition()) {
|
||||
auto enumInfo = getEnumInfo(enumDecl);
|
||||
if (enumInfo.isErrorEnum() && baseName.size() > 4 &&
|
||||
camel_case::getLastWord(baseName) == "Code")
|
||||
baseName = baseName.substr(0, baseName.size() - 4);
|
||||
}
|
||||
}
|
||||
|
||||
// Objective-C protocols may have the suffix "Protocol" appended if
|
||||
// the non-suffixed name would conflict with another entity in the
|
||||
|
||||
@@ -806,16 +806,20 @@ namespace {
|
||||
}
|
||||
|
||||
ImportResult VisitEnumType(const clang::EnumType *type) {
|
||||
auto clangDecl = type->getDecl();
|
||||
auto clangDecl = type->getDecl()->getDefinition();
|
||||
if (!clangDecl) {
|
||||
// FIXME: If the enum has a fixed underlying type, can we use that
|
||||
// instead? Or import it opaquely somehow?
|
||||
return nullptr;
|
||||
}
|
||||
switch (Impl.getEnumKind(clangDecl)) {
|
||||
case EnumKind::Constants: {
|
||||
auto clangDef = clangDecl->getDefinition();
|
||||
// Map anonymous enums with no fixed underlying type to Int /if/
|
||||
// they fit in an Int32. If not, this mapping isn't guaranteed to be
|
||||
// consistent for all platforms we care about.
|
||||
if (!clangDef->isFixed() &&
|
||||
clangDef->getNumPositiveBits() < 32 &&
|
||||
clangDef->getNumNegativeBits() <= 32)
|
||||
if (!clangDecl->isFixed() &&
|
||||
clangDecl->getNumPositiveBits() < 32 &&
|
||||
clangDecl->getNumNegativeBits() <= 32)
|
||||
return Impl.getNamedSwiftType(Impl.getStdlibModule(), "Int");
|
||||
|
||||
// Import the underlying integer type.
|
||||
@@ -1759,14 +1763,16 @@ DefaultArgumentKind ClangImporter::Implementation::inferDefaultArgument(
|
||||
return DefaultArgumentKind::None;
|
||||
|
||||
// Option sets default to "[]" if they have "Options" in their name.
|
||||
if (const clang::EnumType *enumTy = type->getAs<clang::EnumType>())
|
||||
if (nameImporter.getEnumKind(enumTy->getDecl()) == EnumKind::Options) {
|
||||
auto enumName = enumTy->getDecl()->getName();
|
||||
if (const clang::EnumType *enumTy = type->getAs<clang::EnumType>()) {
|
||||
const clang::EnumDecl *enumDef = enumTy->getDecl()->getDefinition();
|
||||
if (nameImporter.getEnumKind(enumDef) == EnumKind::Options) {
|
||||
auto enumName = enumDef->getName();
|
||||
for (auto word : reversed(camel_case::getWords(enumName))) {
|
||||
if (camel_case::sameWordIgnoreFirstCase(word, "options"))
|
||||
return DefaultArgumentKind::EmptyArray;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// NSDictionary arguments default to [:] (or nil, if nullable) if "options",
|
||||
// "attributes", or "userInfo" occur in the argument label or (if there is no
|
||||
|
||||
@@ -8,3 +8,13 @@ typedef SWIFT_ENUM_NAMED(NSInteger, ObjCEnum, "SwiftEnum") {
|
||||
ObjCEnumTwo,
|
||||
ObjCEnumThree
|
||||
};
|
||||
|
||||
enum BareForwardEnum;
|
||||
enum ForwardEnumWithUnderlyingType : int;
|
||||
typedef SWIFT_ENUM_NAMED(NSInteger, ForwardObjCEnum, "ForwardSwiftEnum");
|
||||
|
||||
void forwardBarePointer(enum BareForwardEnum * _Nonnull);
|
||||
void forwardWithUnderlyingValue(enum ForwardEnumWithUnderlyingType);
|
||||
void forwardWithUnderlyingPointer(enum ForwardEnumWithUnderlyingType * _Nonnull);
|
||||
void forwardObjCValue(ForwardObjCEnum);
|
||||
void forwardObjCPointer(ForwardObjCEnum * _Nonnull);
|
||||
|
||||
@@ -9,3 +9,11 @@ func test(_ value: SwiftEnum) {
|
||||
case .three: break
|
||||
} // no error
|
||||
}
|
||||
|
||||
let _: Int = forwardBarePointer // expected-error {{cannot convert value of type '(OpaquePointer) -> Void' to specified type 'Int'}}
|
||||
let _: Int = forwardWithUnderlyingPointer // expected-error {{cannot convert value of type '(OpaquePointer) -> Void' to specified type 'Int'}}
|
||||
let _: Int = forwardObjCPointer // expected-error {{cannot convert value of type '(OpaquePointer) -> Void' to specified type 'Int'}}
|
||||
|
||||
// FIXME: It would be nice to import these as unavailable somehow instead.
|
||||
let _: Int = forwardWithUnderlyingValue // expected-error {{use of unresolved identifier 'forwardWithUnderlyingValue'}}
|
||||
let _: Int = forwardObjCValue // expected-error {{use of unresolved identifier 'forwardObjCValue'}}
|
||||
|
||||
Reference in New Issue
Block a user