[ObjC][Gen] Emit ObjC strings to respective sections (#84300)

Clang emits ObjC strings into special sections

d5e7c27d53/clang/lib/CodeGen/CGObjCMac.cpp (L4056-L4072)

As far as I can tell from `CGObjCMac.cpp`:
* types go into `__objc_methtype`
* class, category, and protocol names go into `__objc_classname`
* method names, property names, and property types go into
`__objc_methname`

See also https://github.com/swiftlang/swift/pull/84236.
This commit is contained in:
Ellis Hoag
2025-09-30 08:42:11 -07:00
committed by GitHub
parent 48fdd9980e
commit 2c919e138e
10 changed files with 134 additions and 76 deletions

View File

@@ -1401,8 +1401,9 @@ void irgen::emitBuiltinCall(IRGenFunction &IGF, const BuiltinInfo &Builtin,
auto clangTy = IGF.IGM.getClangType(valueTy->getCanonicalType());
std::string encoding;
IGF.IGM.getClangASTContext().getObjCEncodingForType(clangTy, encoding);
auto globalString = IGF.IGM.getAddrOfGlobalString(encoding);
auto globalString = IGF.IGM.getAddrOfGlobalString(
encoding, CStringSectionType::ObjCMethodType);
out.add(globalString);
return;
}

View File

@@ -1464,7 +1464,8 @@ namespace {
// struct category_t {
// char const *name;
fields.add(IGM.getAddrOfGlobalString(CategoryName));
fields.add(IGM.getAddrOfGlobalString(CategoryName,
CStringSectionType::ObjCClassName));
// const class_t *theClass;
fields.add(getClassMetadataRef());
// const method_list_t *instanceMethods;
@@ -1503,7 +1504,8 @@ namespace {
// Class super;
fields.addNullPointer(IGM.Int8PtrTy);
// char const *name;
fields.add(IGM.getAddrOfGlobalString(getEntityName(nameBuffer)));
fields.add(IGM.getAddrOfGlobalString(getEntityName(nameBuffer),
CStringSectionType::ObjCClassName));
// const protocol_list_t *baseProtocols;
fields.add(buildProtocolList(weakLinkage));
// const method_list_t *requiredInstanceMethods;
@@ -1724,7 +1726,8 @@ namespace {
}
llvm::SmallString<64> buffer;
Name = IGM.getAddrOfGlobalString(getClass()->getObjCRuntimeName(buffer));
Name = IGM.getAddrOfGlobalString(getClass()->getObjCRuntimeName(buffer),
CStringSectionType::ObjCClassName);
return Name;
}
@@ -2088,11 +2091,10 @@ namespace {
else
fields.addNullPointer(IGM.PtrTy);
// TODO: clang puts this in __TEXT,__objc_methname,cstring_literals
fields.add(IGM.getAddrOfGlobalString(name));
// TODO: clang puts this in __TEXT,__objc_methtype,cstring_literals
fields.add(IGM.getAddrOfGlobalString(typeEnc));
fields.add(
IGM.getAddrOfGlobalString(name, CStringSectionType::ObjCMethodName));
fields.add(IGM.getAddrOfGlobalString(typeEnc,
CStringSectionType::ObjCMethodType));
Size size;
Alignment alignment;
@@ -2228,8 +2230,11 @@ namespace {
buildPropertyAttributes(prop, propertyAttributes);
auto fields = properties.beginStruct();
fields.add(IGM.getAddrOfGlobalString(prop->getObjCPropertyName().str()));
fields.add(IGM.getAddrOfGlobalString(propertyAttributes));
fields.add(
IGM.getAddrOfGlobalString(prop->getObjCPropertyName().str(),
CStringSectionType::ObjCPropertyName));
fields.add(IGM.getAddrOfGlobalString(
propertyAttributes, CStringSectionType::ObjCPropertyName));
fields.finishAndAddTo(properties);
}

View File

@@ -79,7 +79,9 @@ llvm::Constant *irgen::emitAddrOfConstantString(IRGenModule &IGM,
case StringLiteralInst::Encoding::Bytes:
case StringLiteralInst::Encoding::UTF8:
case StringLiteralInst::Encoding::UTF8_OSLOG:
return IGM.getAddrOfGlobalString(SLI->getValue(), false, useOSLogEncoding);
return IGM.getAddrOfGlobalString(
SLI->getValue(), useOSLogEncoding ? CStringSectionType::OSLogString
: CStringSectionType::Default);
case StringLiteralInst::Encoding::ObjCSelector:
llvm_unreachable("cannot get the address of an Objective-C selector");

View File

@@ -296,9 +296,9 @@ public:
// Check if the ObjC runtime already has a descriptor for this
// protocol. If so, use it.
SmallString<32> buf;
auto protocolName
= IGM.getAddrOfGlobalString(proto->getObjCRuntimeName(buf));
auto protocolName = IGM.getAddrOfGlobalString(
proto->getObjCRuntimeName(buf), CStringSectionType::ObjCClassName);
auto existing = Builder.CreateCall(objc_getProtocol, protocolName);
auto isNull = Builder.CreateICmpEQ(existing,
llvm::ConstantPointerNull::get(IGM.ProtocolDescriptorPtrTy));
@@ -1056,16 +1056,14 @@ void IRGenModule::SetCStringLiteralSection(llvm::GlobalVariable *GV,
case llvm::Triple::MachO:
switch (Type) {
case ObjCLabelType::ClassName:
GV->setSection("__TEXT,__objc_classname,cstring_literals");
GV->setSection(IRGenModule::ObjCClassNameSectionName);
return;
case ObjCLabelType::MethodVarName:
GV->setSection("__TEXT,__objc_methname,cstring_literals");
case ObjCLabelType::PropertyName:
GV->setSection(IRGenModule::ObjCMethodNameSectionName);
return;
case ObjCLabelType::MethodVarType:
GV->setSection("__TEXT,__objc_methtype,cstring_literals");
return;
case ObjCLabelType::PropertyName:
GV->setSection("__TEXT,__objc_methname,cstring_literals");
GV->setSection(IRGenModule::ObjCMethodTypeSectionName);
return;
}
case llvm::Triple::ELF:
@@ -4240,9 +4238,10 @@ static TypeEntityReference
getObjCClassByNameReference(IRGenModule &IGM, ClassDecl *cls) {
auto kind = TypeReferenceKind::DirectObjCClassName;
SmallString<64> objcRuntimeNameBuffer;
auto ref = IGM.getAddrOfGlobalString(
cls->getObjCRuntimeName(objcRuntimeNameBuffer),
/*willBeRelativelyAddressed=*/true);
auto ref =
IGM.getAddrOfGlobalString(cls->getObjCRuntimeName(objcRuntimeNameBuffer),
CStringSectionType::ObjCClassName,
/*willBeRelativelyAddressed=*/true);
return TypeEntityReference(kind, ref);
}
@@ -4799,9 +4798,9 @@ void IRGenModule::emitAccessibleFunction(StringRef sectionName,
// -- Field: Name (record name)
{
llvm::Constant *name =
getAddrOfGlobalString(func.getFunctionName(),
/*willBeRelativelyAddressed=*/true);
llvm::Constant *name = getAddrOfGlobalString(
func.getFunctionName(), CStringSectionType::Default,
/*willBeRelativelyAddressed=*/true);
fields.addRelativeAddress(name);
}
@@ -6023,15 +6022,34 @@ Address IRGenFunction::createAlloca(llvm::Type *type,
/// FIXME: willBeRelativelyAddressed is only needed to work around an ld64 bug
/// resolving relative references to coalesceable symbols.
/// It should be removed when fixed. rdar://problem/22674524
llvm::Constant *IRGenModule::getAddrOfGlobalString(StringRef data,
bool willBeRelativelyAddressed,
bool useOSLogSection) {
useOSLogSection = useOSLogSection &&
TargetInfo.OutputObjectFormat == llvm::Triple::MachO;
llvm::Constant *
IRGenModule::getAddrOfGlobalString(StringRef data, CStringSectionType type,
bool willBeRelativelyAddressed) {
if (TargetInfo.OutputObjectFormat != llvm::Triple::MachO)
type = CStringSectionType::Default;
StringRef sectionName;
switch (type) {
case CStringSectionType::Default:
sectionName = "";
break;
case CStringSectionType::ObjCClassName:
sectionName = ObjCClassNameSectionName;
break;
case CStringSectionType::ObjCMethodName:
sectionName = ObjCMethodNameSectionName;
break;
case CStringSectionType::ObjCMethodType:
sectionName = ObjCMethodTypeSectionName;
break;
case CStringSectionType::OSLogString:
sectionName = OSLogStringSectionName;
break;
case CStringSectionType::NumTypes:
llvm_unreachable("invalid type");
}
// Check whether this string already exists.
auto &entry = useOSLogSection ? GlobalOSLogStrings[data] :
GlobalStrings[data];
auto &entry = GlobalStrings[static_cast<size_t>(type)][data];
if (entry.second) {
// FIXME: Clear unnamed_addr if the global will be relative referenced
@@ -6053,9 +6071,6 @@ llvm::Constant *IRGenModule::getAddrOfGlobalString(StringRef data,
(llvm::Twine(".nul") + llvm::Twine(i)).toVector(name);
}
auto sectionName =
useOSLogSection ? "__TEXT,__oslogstring,cstring_literals" : "";
entry = createStringConstant(data, willBeRelativelyAddressed,
sectionName, name);
return entry.second;
@@ -6067,9 +6082,11 @@ IRGenModule::getAddrOfGlobalIdentifierString(StringRef data,
if (Lexer::identifierMustAlwaysBeEscaped(data)) {
llvm::SmallString<256> name;
Mangle::Mangler::appendRawIdentifierForRuntime(data, name);
return getAddrOfGlobalString(name, willBeRelativelyAddressed);
return getAddrOfGlobalString(name, CStringSectionType::Default,
willBeRelativelyAddressed);
}
return getAddrOfGlobalString(data, willBeRelativelyAddressed);
return getAddrOfGlobalString(data, CStringSectionType::Default,
willBeRelativelyAddressed);
}
/// Get or create a global UTF-16 string constant.

View File

@@ -1143,6 +1143,7 @@ IRGenModule::getAddrOfKeyPathPattern(KeyPathPattern *pattern,
// null otherwise.
if (!pattern->getObjCString().empty()) {
auto objcString = getAddrOfGlobalString(pattern->getObjCString(),
CStringSectionType::Default,
/*relatively addressed*/ true);
fields.addRelativeAddress(objcString);
} else {

View File

@@ -845,8 +845,8 @@ namespace {
IRGenMangler mangler(IGM.Context);
auto mangledName = mangler.mangleAnonymousDescriptorName(Name);
auto mangledNameConstant =
IGM.getAddrOfGlobalString(mangledName,
/*willBeRelativelyAddressed*/ true);
IGM.getAddrOfGlobalString(mangledName, CStringSectionType::Default,
/*willBeRelativelyAddressed*/ true);
B.addRelativeAddress(mangledNameConstant);
}
@@ -1277,6 +1277,7 @@ namespace {
llvm::Constant *global = nullptr;
if (!AssociatedTypeNames.empty()) {
global = IGM.getAddrOfGlobalString(AssociatedTypeNames,
CStringSectionType::Default,
/*willBeRelativelyAddressed=*/true);
}
B.addRelativeAddressOrNull(global);
@@ -1515,9 +1516,10 @@ namespace {
name.pop_back();
assert(name.back() == '\0');
}
auto nameStr = IGM.getAddrOfGlobalString(name,
/*willBeRelativelyAddressed*/ true);
auto nameStr =
IGM.getAddrOfGlobalString(name, CStringSectionType::Default,
/*willBeRelativelyAddressed*/ true);
B.addRelativeAddress(nameStr);
}

View File

@@ -1318,7 +1318,8 @@ static llvm::Constant *getObjCEncodingForTypes(IRGenModule &IGM,
encodingString += llvm::itostr(parmOffset);
encodingString += fixedParamsString;
encodingString += paramsString;
return IGM.getAddrOfGlobalString(encodingString);
return IGM.getAddrOfGlobalString(encodingString,
CStringSectionType::ObjCMethodType);
}
static llvm::Constant *
@@ -1329,16 +1330,19 @@ getObjectEncodingFromClangNode(IRGenModule &IGM, Decl *d,
auto clangDecl = d->getClangNode().castAsDecl();
auto &clangASTContext = IGM.getClangASTContext();
std::string typeStr;
CStringSectionType sectionType;
if (auto objcMethodDecl = dyn_cast<clang::ObjCMethodDecl>(clangDecl)) {
typeStr = clangASTContext.getObjCEncodingForMethodDecl(
objcMethodDecl, useExtendedEncoding /*extended*/);
sectionType = CStringSectionType::ObjCMethodType;
}
if (auto objcPropertyDecl = dyn_cast<clang::ObjCPropertyDecl>(clangDecl)) {
typeStr = clangASTContext.getObjCEncodingForPropertyDecl(objcPropertyDecl,
nullptr);
sectionType = CStringSectionType::ObjCPropertyName;
}
if (!typeStr.empty()) {
return IGM.getAddrOfGlobalString(typeStr.c_str());
return IGM.getAddrOfGlobalString(typeStr.c_str(), sectionType);
}
}
return nullptr;
@@ -1434,7 +1438,8 @@ irgen::emitObjCGetterDescriptorParts(IRGenModule &IGM, VarDecl *property) {
TypeStr += llvm::itostr(ParmOffset);
TypeStr += "@0:";
TypeStr += llvm::itostr(PtrSize.getValue());
descriptor.typeEncoding = IGM.getAddrOfGlobalString(TypeStr.c_str());
descriptor.typeEncoding = IGM.getAddrOfGlobalString(
TypeStr.c_str(), CStringSectionType::ObjCMethodType);
descriptor.silFunction = nullptr;
descriptor.impl = getObjCGetterPointer(IGM, property, descriptor.silFunction);
return descriptor;
@@ -1511,7 +1516,8 @@ irgen::emitObjCSetterDescriptorParts(IRGenModule &IGM,
ParmOffset = 2 * PtrSize.getValue();
clangASTContext.getObjCEncodingForType(clangType, TypeStr);
TypeStr += llvm::itostr(ParmOffset);
descriptor.typeEncoding = IGM.getAddrOfGlobalString(TypeStr.c_str());
descriptor.typeEncoding = IGM.getAddrOfGlobalString(
TypeStr.c_str(), CStringSectionType::ObjCMethodType);
descriptor.silFunction = nullptr;
descriptor.impl = getObjCSetterPointer(IGM, property, descriptor.silFunction);
return descriptor;
@@ -1617,7 +1623,8 @@ void irgen::emitObjCIVarInitDestroyDescriptor(IRGenModule &IGM,
auto ptrSize = IGM.getPointerSize().getValue();
llvm::SmallString<8> signature;
signature = "v" + llvm::itostr(ptrSize * 2) + "@0:" + llvm::itostr(ptrSize);
descriptor.typeEncoding = IGM.getAddrOfGlobalString(signature);
descriptor.typeEncoding =
IGM.getAddrOfGlobalString(signature, CStringSectionType::ObjCMethodType);
/// The third element is the method implementation pointer.
descriptor.impl = llvm::ConstantExpr::getBitCast(objcImpl, IGM.Int8PtrTy);

View File

@@ -669,6 +669,18 @@ public:
llvm::Constant *address);
};
enum class CStringSectionType {
Default,
ObjCClassName,
ObjCMethodName,
ObjCMethodType,
OSLogString,
// Place all new section types above this line
NumTypes,
// Place all alias below this line
ObjCPropertyName = ObjCMethodName,
};
/// IRGenModule - Primary class for emitting IR for global declarations.
///
class IRGenModule {
@@ -1203,9 +1215,10 @@ public:
std::pair<llvm::GlobalVariable *, llvm::Constant *> createStringConstant(
StringRef Str, bool willBeRelativelyAddressed = false,
StringRef sectionName = "", StringRef name = "");
llvm::Constant *getAddrOfGlobalString(StringRef utf8,
bool willBeRelativelyAddressed = false,
bool useOSLogSection = false);
llvm::Constant *getAddrOfGlobalString(
StringRef utf8,
CStringSectionType sectionType = CStringSectionType::Default,
bool willBeRelativelyAddressed = false);
llvm::Constant *getAddrOfGlobalUTF16String(StringRef utf8);
llvm::Constant *
getAddrOfGlobalIdentifierString(StringRef utf8,
@@ -1329,10 +1342,11 @@ private:
llvm::DenseMap<LinkEntity, llvm::Constant*> GlobalGOTEquivalents;
llvm::DenseMap<LinkEntity, llvm::Function*> GlobalFuncs;
llvm::DenseSet<const clang::Decl *> GlobalClangDecls;
llvm::StringMap<std::pair<llvm::GlobalVariable*, llvm::Constant*>>
GlobalStrings;
llvm::StringMap<std::pair<llvm::GlobalVariable*, llvm::Constant*>>
GlobalOSLogStrings;
// Maps sectionName -> string data -> constant
std::array<
llvm::StringMap<std::pair<llvm::GlobalVariable *, llvm::Constant *>>,
static_cast<size_t>(CStringSectionType::NumTypes)>
GlobalStrings;
llvm::StringMap<llvm::Constant*> GlobalUTF16Strings;
llvm::StringMap<std::pair<llvm::GlobalVariable*, llvm::Constant*>>
StringsForTypeRef;
@@ -1543,6 +1557,15 @@ public:
const char *getReflectionTypeRefSectionName();
const char *getMultiPayloadEnumDescriptorSectionName();
static constexpr const char ObjCClassNameSectionName[] =
"__TEXT,__objc_classname,cstring_literals";
static constexpr const char ObjCMethodNameSectionName[] =
"__TEXT,__objc_methname,cstring_literals";
static constexpr const char ObjCMethodTypeSectionName[] =
"__TEXT,__objc_methtype,cstring_literals";
static constexpr const char OSLogStringSectionName[] =
"__TEXT,__oslogstring,cstring_literals";
/// Returns the special builtin types that should be emitted in the stdlib
/// module.
llvm::ArrayRef<CanType> getOrCreateSpecialStlibBuiltinTypes();

View File

@@ -39,16 +39,16 @@ public struct NonCopyable: ~Copyable { }
// 'MF' constant as a separator that precedes each field descriptor.
// NEW: @"$s4test8CC_TestsCMF" =
// NEW-SAME: @"get_type_metadata Ri_zr0_l4test21ConditionallyCopyableOyxG.3"
// NEW-SAME: @"get_type_metadata Ri_zr0_l4test21ConditionallyCopyableOyxG.{{[0-9]+}}"
// NEW-SAME: @"symbolic _____yq_G 4test21ConditionallyCopyableOAARi_zrlE"
// NEW-SAME: @"get_type_metadata Ri_zr0_l4test21ConditionallyCopyableOyAA03NonC0VG.4"
// NEW-SAME: @"get_type_metadata Ri_zr0_l4test21ConditionallyCopyableOyAA03NonC0VG.{{[0-9]+}}"
// NEW-SAME: @"symbolic _____ySSG 4test21ConditionallyCopyableOAARi_zrlE"
// OLD: @"$s4test8CC_TestsCMF" =
// OLD-SAME: @"get_type_metadata Ri_zr0_l4test21ConditionallyCopyableOyxG.3"
// OLD-SAME: @"get_type_metadata Ri_zr0_l4test21ConditionallyCopyableOyq_G.4"
// OLD-SAME: @"get_type_metadata Ri_zr0_l4test21ConditionallyCopyableOyAA03NonC0VG.5"
// OLD-SAME: @"get_type_metadata Ri_zr0_l4test21ConditionallyCopyableOySSG.6"
// OLD-SAME: @"get_type_metadata Ri_zr0_l4test21ConditionallyCopyableOyxG.{{[0-9]+}}"
// OLD-SAME: @"get_type_metadata Ri_zr0_l4test21ConditionallyCopyableOyq_G.{{[0-9]+}}"
// OLD-SAME: @"get_type_metadata Ri_zr0_l4test21ConditionallyCopyableOyAA03NonC0VG.{{[0-9]+}}"
// OLD-SAME: @"get_type_metadata Ri_zr0_l4test21ConditionallyCopyableOySSG.{{[0-9]+}}"
public class CC_Tests<NCG: ~Copyable, T> {
var ccNCG: ConditionallyCopyable<NCG> = .none
var ccT: ConditionallyCopyable<T> = .none
@@ -62,16 +62,16 @@ public class CC_Tests<NCG: ~Copyable, T> {
/// fields until a future runtime says they're safe to reflect.
// NEW: @"$s4test8NC_TestsCMF" =
// NEW-SAME: @"get_type_metadata Ri_zr0_l4test13NeverCopyableOyxG.5"
// NEW-SAME: @"get_type_metadata Ri_zr0_l4test13NeverCopyableOyq_G.6"
// NEW-SAME: @"get_type_metadata Ri_zr0_l4test13NeverCopyableOyAA03NonC0VG.7"
// NEW-SAME: @"get_type_metadata Ri_zr0_l4test13NeverCopyableOySSG.8"
// NEW-SAME: @"get_type_metadata Ri_zr0_l4test13NeverCopyableOyxG.{{[0-9]+}}"
// NEW-SAME: @"get_type_metadata Ri_zr0_l4test13NeverCopyableOyq_G.{{[0-9]+}}"
// NEW-SAME: @"get_type_metadata Ri_zr0_l4test13NeverCopyableOyAA03NonC0VG.{{[0-9]+}}"
// NEW-SAME: @"get_type_metadata Ri_zr0_l4test13NeverCopyableOySSG.{{[0-9]+}}"
// OLD: @"$s4test8NC_TestsCMF" =
// OLD-SAME: @"get_type_metadata Ri_zr0_l4test13NeverCopyableOyxG.7"
// OLD-SAME: @"get_type_metadata Ri_zr0_l4test13NeverCopyableOyq_G.8"
// OLD-SAME: @"get_type_metadata Ri_zr0_l4test13NeverCopyableOyAA03NonC0VG.9"
// OLD-SAME: @"get_type_metadata Ri_zr0_l4test13NeverCopyableOySSG.10"
// OLD-SAME: @"get_type_metadata Ri_zr0_l4test13NeverCopyableOyxG.{{[0-9]+}}"
// OLD-SAME: @"get_type_metadata Ri_zr0_l4test13NeverCopyableOyq_G.{{[0-9]+}}"
// OLD-SAME: @"get_type_metadata Ri_zr0_l4test13NeverCopyableOyAA03NonC0VG.{{[0-9]+}}"
// OLD-SAME: @"get_type_metadata Ri_zr0_l4test13NeverCopyableOySSG.{{[0-9]+}}"
public class NC_Tests<NCG: ~Copyable, T> {
var ncNCG: NeverCopyable<NCG> = .none
var ncT: NeverCopyable<T> = .none
@@ -83,7 +83,7 @@ public class NC_Tests<NCG: ~Copyable, T> {
// NEW: @"$s4test17StdlibTypes_TestsCMF" =
// NEW-SAME: @"symbolic xSg"
// NEW-SAME: @"symbolic q_Sg"
// NEW-SAME: @"get_type_metadata Ri_zr0_l4test11NonCopyableVSg.9"
// NEW-SAME: @"get_type_metadata Ri_zr0_l4test11NonCopyableVSg.{{[0-9]+}}"
// NEW-SAME: @"symbolic SSSg"
// NEW-SAME: @"symbolic SPyxG"
// NEW-SAME: @"symbolic SPyq_G"
@@ -93,7 +93,7 @@ public class NC_Tests<NCG: ~Copyable, T> {
// OLD: @"$s4test17StdlibTypes_TestsCMF" =
// OLD-SAME: @"symbolic xSg"
// OLD-SAME: @"symbolic q_Sg"
// OLD-SAME: @"get_type_metadata Ri_zr0_l4test11NonCopyableVSg.11"
// OLD-SAME: @"get_type_metadata Ri_zr0_l4test11NonCopyableVSg.{{[0-9]+}}"
// OLD-SAME: @"symbolic SSSg"
// OLD-SAME: @"symbolic SPyxG"
// OLD-SAME: @"symbolic SPyq_G"
@@ -115,13 +115,13 @@ public class StdlibTypes_Tests<NCG: ~Copyable, T> {
// NEW: @"$s4test19PlainlyStored_TestsCMF" =
// NEW-SAME: @"symbolic x"
// NEW-SAME: @"symbolic q_"
// NEW-SAME: @"get_type_metadata Ri_zr0_l4test11NonCopyableV.10"
// NEW-SAME: @"get_type_metadata Ri_zr0_l4test11NonCopyableV.{{[0-9]+}}"
// NEW-SAME: @"symbolic SS"
// OLD: @"$s4test19PlainlyStored_TestsCMF" =
// OLD-SAME: @"symbolic x"
// OLD-SAME: @"symbolic q_"
// OLD-SAME: @"get_type_metadata Ri_zr0_l4test11NonCopyableV.12"
// OLD-SAME: @"get_type_metadata Ri_zr0_l4test11NonCopyableV.{{[0-9]+}}"
// OLD-SAME: @"symbolic SS"
public class PlainlyStored_Tests<NCG: ~Copyable, T> {
var ncg: NCG

View File

@@ -13,7 +13,7 @@ import objc_extension_base
// Check that metadata for nested enums added in extensions to imported classes
// gets emitted concretely.
// CHECK: [[CATEGORY_NAME:@.*]] = private constant [16 x i8] c"objc_extensions\00"
// CHECK: [[CATEGORY_NAME:@.*]] = private unnamed_addr constant [16 x i8] c"objc_extensions\00"
// CHECK: [[METHOD_TYPE:@.*]] = private unnamed_addr constant [8 x i8] c"v16@0:8\00"
// CHECK-LABEL: @"_CATEGORY_PROTOCOLS_Gizmo_$_objc_extensions" = internal constant