Esempio n. 1
0
/// Classify the given Clang enumeration to describe how to import it.
void EnumInfo::classifyEnum(const clang::EnumDecl *decl,
                            clang::Preprocessor &pp) {
  // Anonymous enumerations simply get mapped to constants of the
  // underlying type of the enum, because there is no way to conjure up a
  // name for the Swift type.
  if (!decl->hasNameForLinkage()) {
    kind = EnumKind::Constants;
    return;
  }

  // First, check for attributes that denote the classification
  if (auto domainAttr = decl->getAttr<clang::NSErrorDomainAttr>()) {
    kind = EnumKind::Enum;
    attribute = domainAttr;
    return;
  }

  // Was the enum declared using *_ENUM or *_OPTIONS?
  // FIXME: Use Clang attributes instead of grovelling the macro expansion loc.
  auto loc = decl->getLocStart();
  if (loc.isMacroID()) {
    StringRef MacroName = pp.getImmediateMacroName(loc);
    if (MacroName == "CF_ENUM" || MacroName == "__CF_NAMED_ENUM" ||
        MacroName == "OBJC_ENUM" || MacroName == "SWIFT_ENUM" ||
        MacroName == "SWIFT_ENUM_NAMED") {
      kind = EnumKind::Enum;
      return;
    }
    if (MacroName == "CF_OPTIONS" || MacroName == "OBJC_OPTIONS" ||
        MacroName == "SWIFT_OPTIONS") {
      kind = EnumKind::Options;
      return;
    }
  }

  // Hardcode a particular annoying case in the OS X headers.
  if (decl->getName() == "DYLD_BOOL") {
    kind = EnumKind::Enum;
    return;
  }

  // Fall back to the 'Unknown' path.
  kind = EnumKind::Unknown;
}
Esempio n. 2
0
/// 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
  // underlying type of the enum, because there is no way to conjure up a
  // name for the Swift type.
  if (!decl->hasNameForLinkage()) {
    kind = EnumKind::Constants;
    return;
  }

  // First, check for attributes that denote the classification
  if (auto domainAttr = decl->getAttr<clang::NSErrorDomainAttr>()) {
    kind = EnumKind::Enum;
    nsErrorDomain = ctx.AllocateCopy(domainAttr->getErrorDomain()->getName());
    return;
  }
  if (decl->hasAttr<clang::FlagEnumAttr>()) {
    kind = EnumKind::Options;
    return;
  }
  if (decl->hasAttr<clang::EnumExtensibilityAttr>()) {
    // FIXME: Distinguish between open and closed enums.
    kind = EnumKind::Enum;
    return;
  }

  // If API notes have /removed/ a FlagEnum or EnumExtensibility attribute,
  // then we don't need to check the macros.
  for (auto *attr : decl->specific_attrs<clang::SwiftVersionedAttr>()) {
    if (!attr->getVersion().empty())
      continue;
    if (isa<clang::FlagEnumAttr>(attr->getAttrToAdd()) ||
        isa<clang::EnumExtensibilityAttr>(attr->getAttrToAdd())) {
      kind = EnumKind::Unknown;
      return;
    }
  }

  // Was the enum declared using *_ENUM or *_OPTIONS?
  // FIXME: Stop using these once flag_enum and enum_extensibility
  // have been adopted everywhere, or at least relegate them to Swift 3 mode
  // only.
  auto loc = decl->getLocStart();
  if (loc.isMacroID()) {
    StringRef MacroName = pp.getImmediateMacroName(loc);
    if (MacroName == "CF_ENUM" || MacroName == "__CF_NAMED_ENUM" ||
        MacroName == "OBJC_ENUM" || MacroName == "SWIFT_ENUM" ||
        MacroName == "SWIFT_ENUM_NAMED") {
      kind = EnumKind::Enum;
      return;
    }
    if (MacroName == "CF_OPTIONS" || MacroName == "OBJC_OPTIONS" ||
        MacroName == "SWIFT_OPTIONS") {
      kind = EnumKind::Options;
      return;
    }
  }

  // Hardcode a particular annoying case in the OS X headers.
  if (decl->getName() == "DYLD_BOOL") {
    kind = EnumKind::Enum;
    return;
  }

  // Fall back to the 'Unknown' path.
  kind = EnumKind::Unknown;
}