//===--- ClangAdapter.cpp - Interfaces with Clang entities ----------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// This file provides convenient and canonical interfaces with Clang entities,
// serving as both a useful place to put utility functions and a canonical
// interface that can abstract nitty gritty Clang internal details.
//
//===----------------------------------------------------------------------===//

#include "CFTypeInfo.h"
#include "ClangAdapter.h"
#include "ImportName.h"
#include "ImporterImpl.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclObjC.h"
#include "clang/Lex/Lexer.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/Sema.h"

using namespace swift;
using namespace importer;

/// Get a bit vector indicating which arguments are non-null for a
/// given function or method.
llvm::SmallBitVector
importer::getNonNullArgs(const clang::Decl *decl,
                         ArrayRef<const clang::ParmVarDecl *> params) {
  llvm::SmallBitVector result;
  if (!decl)
    return result;

  for (const auto *nonnull : decl->specific_attrs<clang::NonNullAttr>()) {
    if (!nonnull->args_size()) {
      // Easy case: all pointer arguments are non-null.
      if (result.empty())
        result.resize(params.size(), true);
      else
        result.set(0, params.size());

      return result;
    }

    // Mark each of the listed parameters as non-null.
    if (result.empty())
      result.resize(params.size(), false);

    for (unsigned idx : nonnull->args()) {
      if (idx < result.size())
        result.set(idx);
    }
  }

  return result;
}

Optional<const clang::Decl *>
importer::getDefinitionForClangTypeDecl(const clang::Decl *D) {
  if (auto OID = dyn_cast<clang::ObjCInterfaceDecl>(D))
    return OID->getDefinition();

  if (auto TD = dyn_cast<clang::TagDecl>(D))
    return TD->getDefinition();

  if (auto OPD = dyn_cast<clang::ObjCProtocolDecl>(D))
    return OPD->getDefinition();

  return None;
}

Optional<clang::Module *>
importer::getClangSubmoduleForDecl(const clang::Decl *D,
                                   bool allowForwardDeclaration) {
  const clang::Decl *actual = nullptr;

  // Put an Objective-C class into the module that contains the @interface
  // definition, not just some @class forward declaration.
  if (auto maybeDefinition = getDefinitionForClangTypeDecl(D)) {
    actual = maybeDefinition.getValue();
    if (!actual && !allowForwardDeclaration)
      return None;
  }

  if (!actual)
    actual = D->getCanonicalDecl();

  return actual->getImportedOwningModule();
}

/// Retrieve the instance type of the given Clang declaration context.
clang::QualType
importer::getClangDeclContextType(const clang::DeclContext *dc) {
  auto &ctx = dc->getParentASTContext();
  if (auto objcClass = dyn_cast<clang::ObjCInterfaceDecl>(dc))
    return ctx.getObjCObjectPointerType(ctx.getObjCInterfaceType(objcClass));

  if (auto objcCategory = dyn_cast<clang::ObjCCategoryDecl>(dc)) {
    if (objcCategory->isInvalidDecl())
      return clang::QualType();

    return ctx.getObjCObjectPointerType(
        ctx.getObjCInterfaceType(objcCategory->getClassInterface()));
  }

  if (auto constProto = dyn_cast<clang::ObjCProtocolDecl>(dc)) {
    auto proto = const_cast<clang::ObjCProtocolDecl *>(constProto);
    auto type = ctx.getObjCObjectType(ctx.ObjCBuiltinIdTy, {}, {proto}, false);
    return ctx.getObjCObjectPointerType(type);
  }

  if (auto tag = dyn_cast<clang::TagDecl>(dc)) {
    return ctx.getTagDeclType(tag);
  }

  return clang::QualType();
}

/// Determine whether this is the name of a collection with a single
/// element type.
static bool isCollectionName(StringRef typeName) {
  auto lastWord = camel_case::getLastWord(typeName);
  return lastWord == "Array" || lastWord == "Set";
}

/// Retrieve the name of the given Clang type for use when omitting
/// needless words.
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::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::Overload:
    case clang::BuiltinType::PseudoObject:
    case clang::BuiltinType::UnknownAny:
      return OmissionTypeName();

    // FIXME: Types that can be mapped, but aren't yet.
    case clang::BuiltinType::Half:
    case clang::BuiltinType::LongDouble:
    case clang::BuiltinType::Float16:
    case clang::BuiltinType::Float128:
    case clang::BuiltinType::NullPtr:
      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:
      return OmissionTypeName();

    // OpenMP types that don't have Swift equivalents.
    case clang::BuiltinType::OMPArraySection:
      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();
}

static clang::SwiftNewtypeAttr *
retrieveNewTypeAttr(const clang::TypedefNameDecl *decl) {
  // Retrieve the attribute.
  auto attr = decl->getAttr<clang::SwiftNewtypeAttr>();
  if (!attr)
    return nullptr;

  // FIXME: CFErrorDomain is marked as CF_EXTENSIBLE_STRING_ENUM, but it turned
  // out to be more disruptive than not to leave it that way.
  auto name = decl->getName();
  if (name == "CFErrorDomain")
    return nullptr;

  return attr;
}

clang::SwiftNewtypeAttr *
importer::getSwiftNewtypeAttr(const clang::TypedefNameDecl *decl,
                              ImportNameVersion version) {
  // Newtype was introduced in Swift 3
  if (version <= ImportNameVersion::swift2())
    return nullptr;
  return retrieveNewTypeAttr(decl);
}

// If this decl is associated with a swift_newtype typedef, return it, otherwise
// null
clang::TypedefNameDecl *importer::findSwiftNewtype(const clang::NamedDecl *decl,
                                                   clang::Sema &clangSema,
                                                   ImportNameVersion version) {
  // Newtype was introduced in Swift 3
  if (version <= ImportNameVersion::swift2())
    return nullptr;

  auto varDecl = dyn_cast<clang::VarDecl>(decl);
  if (!varDecl)
    return nullptr;

  if (auto typedefTy = varDecl->getType()->getAs<clang::TypedefType>())
    if (retrieveNewTypeAttr(typedefTy->getDecl()))
      return typedefTy->getDecl();

  // Special case: "extern NSString * fooNotification" adopts
  // NSNotificationName type, and is a member of NSNotificationName
  if (isNSNotificationGlobal(decl)) {
    clang::IdentifierInfo *notificationName =
        &clangSema.getASTContext().Idents.get("NSNotificationName");
    clang::LookupResult lookupResult(clangSema, notificationName,
                                     clang::SourceLocation(),
                                     clang::Sema::LookupOrdinaryName);
    if (!clangSema.LookupName(lookupResult, nullptr))
      return nullptr;
    auto nsDecl = lookupResult.getAsSingle<clang::TypedefNameDecl>();
    if (!nsDecl)
      return nullptr;

    // Make sure it also has a newtype decl on it
    if (retrieveNewTypeAttr(nsDecl))
      return nsDecl;

    return nullptr;
  }

  return nullptr;
}

bool importer::isNSString(const clang::Type *type) {
  if (auto ptrType = type->getAs<clang::ObjCObjectPointerType>())
    if (auto interfaceType = ptrType->getInterfaceType())
      if (interfaceType->getDecl()->getName() == "NSString")
        return true;
  return false;
}

bool importer::isNSString(clang::QualType qt) {
  return qt.getTypePtrOrNull() && isNSString(qt.getTypePtrOrNull());
}

bool importer::isNSNotificationGlobal(const clang::NamedDecl *decl) {
  // Looking for: extern NSString *fooNotification;

  // Must be extern global variable
  auto vDecl = dyn_cast<clang::VarDecl>(decl);
  if (!vDecl || !vDecl->hasExternalFormalLinkage())
    return false;

  // No explicit swift_name
  if (decl->getAttr<clang::SwiftNameAttr>())
    return false;

  // Must end in Notification
  if (!vDecl->getDeclName().isIdentifier())
    return false;
  if (stripNotification(vDecl->getName()).empty())
    return false;

  // Must be NSString *
  if (!isNSString(vDecl->getType()))
    return false;

  // We're a match!
  return true;
}

bool importer::hasNativeSwiftDecl(const clang::Decl *decl) {
  for (auto annotation : decl->specific_attrs<clang::AnnotateAttr>()) {
    if (annotation->getAnnotation() == SWIFT_NATIVE_ANNOTATION_STRING) {
      return true;
    }
  }

  if (auto *category = dyn_cast<clang::ObjCCategoryDecl>(decl)) {
    clang::SourceLocation categoryNameLoc = category->getCategoryNameLoc();
    if (categoryNameLoc.isMacroID()) {
      // Climb up to the top-most macro invocation.
      clang::ASTContext &clangCtx = category->getASTContext();
      clang::SourceManager &SM = clangCtx.getSourceManager();

      clang::SourceLocation macroCaller =
          SM.getImmediateMacroCallerLoc(categoryNameLoc);
      while (macroCaller.isMacroID()) {
        categoryNameLoc = macroCaller;
        macroCaller = SM.getImmediateMacroCallerLoc(categoryNameLoc);
      }

      StringRef macroName = clang::Lexer::getImmediateMacroName(
          categoryNameLoc, SM, clangCtx.getLangOpts());
      if (macroName == "SWIFT_EXTENSION")
        return true;
    }
  }

  return false;
}

/// Translate the "nullability" notion from API notes into an optional type
/// kind.
OptionalTypeKind importer::translateNullability(clang::NullabilityKind kind) {
  switch (kind) {
  case clang::NullabilityKind::NonNull:
    return OptionalTypeKind::OTK_None;

  case clang::NullabilityKind::Nullable:
    return OptionalTypeKind::OTK_Optional;

  case clang::NullabilityKind::Unspecified:
    return OptionalTypeKind::OTK_ImplicitlyUnwrappedOptional;
  }

  llvm_unreachable("Invalid NullabilityKind.");
}

bool importer::hasDesignatedInitializers(
    const clang::ObjCInterfaceDecl *classDecl) {
  if (classDecl->hasDesignatedInitializers())
    return true;

  return false;
}

bool importer::isDesignatedInitializer(
    const clang::ObjCInterfaceDecl *classDecl,
    const clang::ObjCMethodDecl *method) {
  // If the information is on the AST, use it.
  if (classDecl->hasDesignatedInitializers()) {
    auto *methodParent = method->getClassInterface();
    if (!methodParent ||
        methodParent->getCanonicalDecl() == classDecl->getCanonicalDecl()) {
      return method->hasAttr<clang::ObjCDesignatedInitializerAttr>();
    }
  }

  return false;
}

bool importer::isRequiredInitializer(const clang::ObjCMethodDecl *method) {
  // FIXME: No way to express this in Objective-C.
  return false;
}

/// Check if this method is declared in the context that conforms to
/// NSAccessibility.
static bool isAccessibilityConformingContext(const clang::DeclContext *ctx) {
  const clang::ObjCProtocolList *protocols = nullptr;

  if (auto protocol = dyn_cast<clang::ObjCProtocolDecl>(ctx)) {
    if (protocol->getName() == "NSAccessibility")
      return true;
    return false;
  } else if (auto interface = dyn_cast<clang::ObjCInterfaceDecl>(ctx))
    protocols = &interface->getReferencedProtocols();
  else if (auto category = dyn_cast<clang::ObjCCategoryDecl>(ctx))
    protocols = &category->getReferencedProtocols();
  else
    return false;

  for (auto pi : *protocols) {
    if (pi->getName() == "NSAccessibility")
      return true;
  }
  return false;
}

bool
importer::shouldImportPropertyAsAccessors(const clang::ObjCPropertyDecl *prop) {
  if (prop->hasAttr<clang::SwiftImportPropertyAsAccessorsAttr>())
    return true;

  // Check if the property is one of the specially handled accessibility APIs.
  //
  // These appear as both properties and methods in ObjC and should be
  // imported as methods into Swift, as a sort of least-common-denominator
  // compromise.
  if (!prop->getName().startswith("accessibility"))
    return false;
  if (isAccessibilityConformingContext(prop->getDeclContext()))
    return true;

  return false;
}

bool importer::isInitMethod(const clang::ObjCMethodDecl *method) {
  // init methods are always instance methods.
  if (!method->isInstanceMethod())
    return false;

  // init methods must be classified as such by Clang.
  if (method->getMethodFamily() != clang::OMF_init)
    return false;

  // Swift restriction: init methods must start with the word "init".
  auto selector = method->getSelector();
  return camel_case::getFirstWord(selector.getNameForSlot(0)) == "init";
}

bool importer::isObjCId(const clang::Decl *decl) {
  auto typedefDecl = dyn_cast<clang::TypedefNameDecl>(decl);
  if (!typedefDecl)
    return false;

  if (!typedefDecl->getDeclContext()->getRedeclContext()->isTranslationUnit())
    return false;

  return typedefDecl->getName() == "id";
}

bool importer::isUnavailableInSwift(
    const clang::Decl *decl, const PlatformAvailability &platformAvailability,
    bool enableObjCInterop) {
  // 'id' is always unavailable in Swift.
  if (enableObjCInterop && isObjCId(decl))
    return true;

  if (decl->isUnavailable())
    return true;

  for (auto *attr : decl->specific_attrs<clang::AvailabilityAttr>()) {
    if (attr->getPlatform()->getName() == "swift")
      return true;

    if (platformAvailability.filter &&
        !platformAvailability.filter(attr->getPlatform()->getName())) {
      continue;
    }

    if (platformAvailability.deprecatedAsUnavailableFilter) {
      clang::VersionTuple version = attr->getDeprecated();
      if (version.empty())
        continue;
      if (platformAvailability.deprecatedAsUnavailableFilter(
            version.getMajor(), version.getMinor())) {
        return true;
      }
    }
  }

  return false;
}

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

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

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

  // Check for the 'static' annotation on C arrays.
  if (!swiftVersion.isVersion3())
    if (const auto *DT = dyn_cast<clang::DecayedType>(paramTy))
      if (const auto *AT = DT->getOriginalType()->getAsArrayTypeUnsafe())
        if (AT->getSizeModifier() == clang::ArrayType::Static)
          return OTK_None;

  // Default to implicitly unwrapped optionals.
  return OTK_ImplicitlyUnwrappedOptional;
}
