in lib/ClangImporter/ClangAdapter.cpp [162:505]
OmissionTypeName importer::getClangTypeNameForOmission(clang::ASTContext &ctx,
clang::QualType type) {
if (type.isNull())
return OmissionTypeName();
// Dig through the type, looking for a typedef-name and stripping
// references along the way.
StringRef lastTypedefName;
do {
// The name of a typedef-name.
auto typePtr = type.getTypePtr();
if (auto typedefType = dyn_cast<clang::TypedefType>(typePtr)) {
auto name = typedefType->getDecl()->getName();
// Objective-C selector type.
if (ctx.hasSameUnqualifiedType(type, ctx.getObjCSelType()) &&
name == "SEL")
return "Selector";
// Objective-C "id" type.
if (type->isObjCIdType() && name == "id")
return "Object";
// Objective-C "Class" type.
if (type->isObjCClassType() && name == "Class")
return "Class";
// Objective-C "BOOL" type.
if (name == "BOOL")
return OmissionTypeName("Bool", OmissionTypeFlags::Boolean);
// If this is an imported CF type, use that name.
StringRef CFName = getCFTypeName(typedefType->getDecl());
if (!CFName.empty())
return CFName;
// If we have NS(U)Integer or CGFloat, return it.
if (name == "NSInteger" || name == "NSUInteger" || name == "CGFloat")
return name;
// If it's a collection name and of pointer type, call it an
// array of the pointee type.
if (isCollectionName(name)) {
if (auto ptrType = type->getAs<clang::PointerType>()) {
return OmissionTypeName(
name, None,
getClangTypeNameForOmission(ctx, ptrType->getPointeeType()).Name);
}
}
// Otherwise, desugar one level...
lastTypedefName = name;
type = typedefType->getDecl()->getUnderlyingType();
continue;
}
// For array types, convert the element type and treat this an as array.
if (auto arrayType = dyn_cast<clang::ArrayType>(typePtr)) {
return OmissionTypeName(
"Array", None,
getClangTypeNameForOmission(ctx, arrayType->getElementType()).Name);
}
// Look through reference types.
if (auto refType = dyn_cast<clang::ReferenceType>(typePtr)) {
type = refType->getPointeeTypeAsWritten();
continue;
}
// Look through pointer types.
if (auto ptrType = dyn_cast<clang::PointerType>(typePtr)) {
type = ptrType->getPointeeType();
continue;
}
// Try to desugar one level...
clang::QualType desugared = type.getSingleStepDesugaredType(ctx);
if (desugared.getTypePtr() == type.getTypePtr())
break;
type = desugared;
} while (true);
// Objective-C object pointers.
if (auto objcObjectPtr = type->getAs<clang::ObjCObjectPointerType>()) {
auto objcClass = objcObjectPtr->getInterfaceDecl();
// For id<Proto> or NSObject<Proto>, retrieve the name of "Proto".
if (objcObjectPtr->getNumProtocols() == 1 &&
(!objcClass || objcClass->getName() == "NSObject"))
return (*objcObjectPtr->qual_begin())->getName();
// If there is a class, use it.
if (objcClass) {
// If this isn't the name of an Objective-C collection, we're done.
auto className = objcClass->getName();
if (!isCollectionName(className))
return className;
// If we don't have type parameters, use the prefix of the type
// name as the collection element type.
if (objcClass && !objcClass->getTypeParamList()) {
unsigned lastWordSize = camel_case::getLastWord(className).size();
StringRef elementName =
className.substr(0, className.size() - lastWordSize);
return OmissionTypeName(className, None, elementName);
}
// If we don't have type arguments, the collection element type
// is "Object".
auto typeArgs = objcObjectPtr->getTypeArgs();
if (typeArgs.empty())
return OmissionTypeName(className, None, "Object");
return OmissionTypeName(
className, None, getClangTypeNameForOmission(ctx, typeArgs[0]).Name);
}
// Objective-C "id" type.
if (objcObjectPtr->isObjCIdType())
return "Object";
// Objective-C "Class" type.
if (objcObjectPtr->isObjCClassType())
return "Class";
return StringRef();
}
// Handle builtin types by importing them and getting the Swift name.
if (auto builtinTy = type->getAs<clang::BuiltinType>()) {
// Names of integer types.
static const char *intTypeNames[] = {"UInt8", "UInt16", "UInt32", "UInt64",
"UInt128"};
/// Retrieve the name for an integer type based on its size.
auto getIntTypeName = [&](bool isSigned) -> StringRef {
switch (ctx.getTypeSize(builtinTy)) {
case 8:
return StringRef(intTypeNames[0]).substr(isSigned ? 1 : 0);
case 16:
return StringRef(intTypeNames[1]).substr(isSigned ? 1 : 0);
case 32:
return StringRef(intTypeNames[2]).substr(isSigned ? 1 : 0);
case 64:
return StringRef(intTypeNames[3]).substr(isSigned ? 1 : 0);
case 128:
return StringRef(intTypeNames[4]).substr(isSigned ? 1 : 0);
default:
llvm_unreachable("bad integer type size");
}
};
switch (builtinTy->getKind()) {
case clang::BuiltinType::Void:
return "Void";
case clang::BuiltinType::Bool:
return OmissionTypeName("Bool", OmissionTypeFlags::Boolean);
case clang::BuiltinType::Float:
return "Float";
case clang::BuiltinType::Double:
return "Double";
case clang::BuiltinType::Char8:
return "UInt8";
case clang::BuiltinType::Char16:
return "UInt16";
case clang::BuiltinType::Char32:
return "UnicodeScalar";
case clang::BuiltinType::Char_U:
case clang::BuiltinType::UChar:
case clang::BuiltinType::UShort:
case clang::BuiltinType::UInt:
case clang::BuiltinType::ULong:
case clang::BuiltinType::ULongLong:
case clang::BuiltinType::UInt128:
case clang::BuiltinType::WChar_U:
return getIntTypeName(false);
case clang::BuiltinType::Char_S:
case clang::BuiltinType::SChar:
case clang::BuiltinType::Short:
case clang::BuiltinType::Int:
case clang::BuiltinType::Long:
case clang::BuiltinType::LongLong:
case clang::BuiltinType::Int128:
case clang::BuiltinType::WChar_S:
return getIntTypeName(true);
// Types that cannot be mapped into Swift, and probably won't ever be.
case clang::BuiltinType::Dependent:
case clang::BuiltinType::ARCUnbridgedCast:
case clang::BuiltinType::BoundMember:
case clang::BuiltinType::BuiltinFn:
case clang::BuiltinType::IncompleteMatrixIdx:
case clang::BuiltinType::Overload:
case clang::BuiltinType::PseudoObject:
case clang::BuiltinType::UnknownAny:
return OmissionTypeName();
// FIXME: Types that can be mapped, but aren't yet.
case clang::BuiltinType::ShortAccum:
case clang::BuiltinType::Accum:
case clang::BuiltinType::LongAccum:
case clang::BuiltinType::UShortAccum:
case clang::BuiltinType::UAccum:
case clang::BuiltinType::ULongAccum:
case clang::BuiltinType::ShortFract:
case clang::BuiltinType::Fract:
case clang::BuiltinType::LongFract:
case clang::BuiltinType::UShortFract:
case clang::BuiltinType::UFract:
case clang::BuiltinType::ULongFract:
case clang::BuiltinType::SatShortAccum:
case clang::BuiltinType::SatAccum:
case clang::BuiltinType::SatLongAccum:
case clang::BuiltinType::SatUShortAccum:
case clang::BuiltinType::SatUAccum:
case clang::BuiltinType::SatULongAccum:
case clang::BuiltinType::SatShortFract:
case clang::BuiltinType::SatFract:
case clang::BuiltinType::SatLongFract:
case clang::BuiltinType::SatUShortFract:
case clang::BuiltinType::SatUFract:
case clang::BuiltinType::SatULongFract:
case clang::BuiltinType::Half:
case clang::BuiltinType::LongDouble:
case clang::BuiltinType::BFloat16:
case clang::BuiltinType::Float16:
case clang::BuiltinType::Float128:
case clang::BuiltinType::NullPtr:
case clang::BuiltinType::Ibm128:
return OmissionTypeName();
// Objective-C types that aren't mapped directly; rather, pointers to
// these types will be mapped.
case clang::BuiltinType::ObjCClass:
case clang::BuiltinType::ObjCId:
case clang::BuiltinType::ObjCSel:
return OmissionTypeName();
// OpenCL types that don't have Swift equivalents.
case clang::BuiltinType::OCLImage1dRO:
case clang::BuiltinType::OCLImage1dRW:
case clang::BuiltinType::OCLImage1dWO:
case clang::BuiltinType::OCLImage1dArrayRO:
case clang::BuiltinType::OCLImage1dArrayRW:
case clang::BuiltinType::OCLImage1dArrayWO:
case clang::BuiltinType::OCLImage1dBufferRO:
case clang::BuiltinType::OCLImage1dBufferRW:
case clang::BuiltinType::OCLImage1dBufferWO:
case clang::BuiltinType::OCLImage2dRO:
case clang::BuiltinType::OCLImage2dRW:
case clang::BuiltinType::OCLImage2dWO:
case clang::BuiltinType::OCLImage2dArrayRO:
case clang::BuiltinType::OCLImage2dArrayRW:
case clang::BuiltinType::OCLImage2dArrayWO:
case clang::BuiltinType::OCLImage2dDepthRO:
case clang::BuiltinType::OCLImage2dDepthRW:
case clang::BuiltinType::OCLImage2dDepthWO:
case clang::BuiltinType::OCLImage2dArrayDepthRO:
case clang::BuiltinType::OCLImage2dArrayDepthRW:
case clang::BuiltinType::OCLImage2dArrayDepthWO:
case clang::BuiltinType::OCLImage2dMSAARO:
case clang::BuiltinType::OCLImage2dMSAARW:
case clang::BuiltinType::OCLImage2dMSAAWO:
case clang::BuiltinType::OCLImage2dArrayMSAARO:
case clang::BuiltinType::OCLImage2dArrayMSAARW:
case clang::BuiltinType::OCLImage2dArrayMSAAWO:
case clang::BuiltinType::OCLImage2dMSAADepthRO:
case clang::BuiltinType::OCLImage2dMSAADepthRW:
case clang::BuiltinType::OCLImage2dMSAADepthWO:
case clang::BuiltinType::OCLImage2dArrayMSAADepthRO:
case clang::BuiltinType::OCLImage2dArrayMSAADepthRW:
case clang::BuiltinType::OCLImage2dArrayMSAADepthWO:
case clang::BuiltinType::OCLImage3dRO:
case clang::BuiltinType::OCLImage3dRW:
case clang::BuiltinType::OCLImage3dWO:
case clang::BuiltinType::OCLSampler:
case clang::BuiltinType::OCLEvent:
case clang::BuiltinType::OCLClkEvent:
case clang::BuiltinType::OCLQueue:
case clang::BuiltinType::OCLReserveID:
case clang::BuiltinType::OCLIntelSubgroupAVCMcePayload:
case clang::BuiltinType::OCLIntelSubgroupAVCImePayload:
case clang::BuiltinType::OCLIntelSubgroupAVCRefPayload:
case clang::BuiltinType::OCLIntelSubgroupAVCSicPayload:
case clang::BuiltinType::OCLIntelSubgroupAVCMceResult:
case clang::BuiltinType::OCLIntelSubgroupAVCImeResult:
case clang::BuiltinType::OCLIntelSubgroupAVCRefResult:
case clang::BuiltinType::OCLIntelSubgroupAVCSicResult:
case clang::BuiltinType::OCLIntelSubgroupAVCImeResultSingleRefStreamout:
case clang::BuiltinType::OCLIntelSubgroupAVCImeResultDualRefStreamout:
case clang::BuiltinType::OCLIntelSubgroupAVCImeSingleRefStreamin:
case clang::BuiltinType::OCLIntelSubgroupAVCImeDualRefStreamin:
return OmissionTypeName();
// OpenMP types that don't have Swift equivalents.
case clang::BuiltinType::OMPArraySection:
case clang::BuiltinType::OMPArrayShaping:
case clang::BuiltinType::OMPIterator:
return OmissionTypeName();
// ARM SVE builtin types that don't have Swift equivalents.
#define SVE_TYPE(Name, Id, ...) case clang::BuiltinType::Id:
#include "clang/Basic/AArch64SVEACLETypes.def"
return OmissionTypeName();
// PPC MMA builtin types that don't have Swift equivalents.
#define PPC_VECTOR_TYPE(Name, Id, Size) case clang::BuiltinType::Id:
#include "clang/Basic/PPCTypes.def"
return OmissionTypeName();
// RISC-V V builtin types that don't have Swift equivalents.
#define RVV_TYPE(Name, Id, Size) case clang::BuiltinType::Id:
#include "clang/Basic/RISCVVTypes.def"
return OmissionTypeName();
}
}
// Tag types.
if (auto tagType = type->getAs<clang::TagType>()) {
if (tagType->getDecl()->getName().empty())
return lastTypedefName;
return tagType->getDecl()->getName();
}
// Block pointers.
if (type->getAs<clang::BlockPointerType>())
return OmissionTypeName("Block", OmissionTypeFlags::Function);
// Function pointers.
if (type->isFunctionType())
return OmissionTypeName("Function", OmissionTypeFlags::Function);
return StringRef();
}