CXXCtorInitializer **IvarInitializers;
unsigned NumIvarInitializers;
- /// true if class has a .cxx_[construct,destruct] method.
- bool HasCXXStructors : 1;
+ /// Do the ivars of this class require initialization other than
+ /// zero-initialization?
+ bool HasNonZeroConstructors : 1;
+
+ /// Do the ivars of this class require non-trivial destruction?
+ bool HasDestructors : 1;
ObjCImplementationDecl(DeclContext *DC,
ObjCInterfaceDecl *classInterface,
SuperClass(superDecl), IvarLBraceLoc(IvarLBraceLoc),
IvarRBraceLoc(IvarRBraceLoc),
IvarInitializers(0), NumIvarInitializers(0),
- HasCXXStructors(false) {}
+ HasNonZeroConstructors(false), HasDestructors(false) {}
public:
static ObjCImplementationDecl *Create(ASTContext &C, DeclContext *DC,
ObjCInterfaceDecl *classInterface,
CXXCtorInitializer ** initializers,
unsigned numInitializers);
- bool hasCXXStructors() const { return HasCXXStructors; }
- void setHasCXXStructors(bool val) { HasCXXStructors = val; }
+ /// Do any of the ivars of this class (not counting its base classes)
+ /// require construction other than zero-initialization?
+ bool hasNonZeroConstructors() const { return HasNonZeroConstructors; }
+ void setHasNonZeroConstructors(bool val) { HasNonZeroConstructors = val; }
+
+ /// Do any of the ivars of this class (not counting its base classes)
+ /// require non-trivial destruction?
+ bool hasDestructors() const { return HasDestructors; }
+ void setHasDestructors(bool val) { HasDestructors = val; }
/// getIdentifier - Get the identifier that names the class
/// interface associated with this implementation.
NonFragileABI_Class_HasIvarReleaser = 0x00040,
/// Class implementation was compiled under ARC.
- NonFragileABI_Class_CompiledByARC = 0x00080
+ NonFragileABI_Class_CompiledByARC = 0x00080,
+
+ /// Class has non-trivial destructors, but zero-initialization is okay.
+ NonFragileABI_Class_HasCXXDestructorOnly = 0x00100
};
/*
Interface->all_referenced_protocol_begin(),
Interface->all_referenced_protocol_end());
unsigned Flags = FragileABI_Class_Factory;
- if (ID->hasCXXStructors())
+ if (ID->hasNonZeroConstructors() || ID->hasDestructors())
Flags |= FragileABI_Class_HasCXXStructors;
unsigned Size =
CGM.getContext().getASTObjCImplementationLayout(ID).getSize().getQuantity();
llvm::GlobalVariable *SuperClassGV, *IsAGV;
+ // Build the flags for the metaclass.
bool classIsHidden =
ID->getClassInterface()->getVisibility() == HiddenVisibility;
if (classIsHidden)
flags |= NonFragileABI_Class_Hidden;
- if (ID->hasCXXStructors())
+
+ // FIXME: why is this flag set on the metaclass?
+ // ObjC metaclasses have no fields and don't really get constructed.
+ if (ID->hasNonZeroConstructors() || ID->hasDestructors()) {
flags |= NonFragileABI_Class_HasCXXStructors;
+ if (!ID->hasNonZeroConstructors())
+ flags |= NonFragileABI_Class_HasCXXDestructorOnly;
+ }
+
if (!ID->getClassInterface()->getSuperClass()) {
// class is root
flags |= NonFragileABI_Class_Root;
flags = 0;
if (classIsHidden)
flags |= NonFragileABI_Class_Hidden;
- if (ID->hasCXXStructors())
+
+ if (ID->hasNonZeroConstructors() || ID->hasDestructors()) {
flags |= NonFragileABI_Class_HasCXXStructors;
+ // Set a flag to enable a runtime optimization when a class has
+ // fields that require destruction but which don't require
+ // anything except zero-initialization during construction. This
+ // is most notably true of __strong and __weak types, but you can
+ // also imagine there being C++ types with non-trivial default
+ // constructors that merely set all fields to null.
+ if (!ID->hasNonZeroConstructors())
+ flags |= NonFragileABI_Class_HasCXXDestructorOnly;
+ }
+
if (hasObjCExceptionAttribute(CGM.getContext(), ID->getClassInterface()))
flags |= NonFragileABI_Class_Exception;
/*isDefined=*/false, ObjCMethodDecl::Required);
D->addInstanceMethod(DTORMethod);
CodeGenFunction(*this).GenerateObjCCtorDtorMethod(D, DTORMethod, false);
- D->setHasCXXStructors(true);
+ D->setHasDestructors(true);
}
// If the implementation doesn't have any ivar initializers, we don't need
ObjCMethodDecl::Required);
D->addInstanceMethod(CTORMethod);
CodeGenFunction(*this).GenerateObjCCtorDtorMethod(D, CTORMethod, true);
- D->setHasCXXStructors(true);
+ D->setHasNonZeroConstructors(true);
}
/// EmitNamespace - Emit all declarations in a namespace.
D->setSuperClass(ReadDeclAs<ObjCInterfaceDecl>(Record, Idx));
D->setIvarLBraceLoc(ReadSourceLocation(Record, Idx));
D->setIvarRBraceLoc(ReadSourceLocation(Record, Idx));
+ D->setHasNonZeroConstructors(Record[Idx++]);
+ D->setHasDestructors(Record[Idx++]);
llvm::tie(D->IvarInitializers, D->NumIvarInitializers)
= Reader.ReadCXXCtorInitializers(F, Record, Idx);
}
Writer.AddDeclRef(D->getSuperClass(), Record);
Writer.AddSourceLocation(D->getIvarLBraceLoc(), Record);
Writer.AddSourceLocation(D->getIvarRBraceLoc(), Record);
+ Record.push_back(D->hasNonZeroConstructors());
+ Record.push_back(D->hasDestructors());
Writer.AddCXXCtorInitializers(D->IvarInitializers, D->NumIvarInitializers,
Record);
Code = serialization::DECL_OBJC_IMPLEMENTATION;
// rdar://problem/8922540
// Note that we no longer emit .release_ivars flags.
-// CHECK-GLOBALS: @"\01l_OBJC_CLASS_RO_$_Test23" = internal global [[RO_T:%.*]] { i32 134,
+// rdar://problem/12492434
+// Note that we set the flag saying that we need destruction *and*
+// the flag saying that we don't also need construction.
+// CHECK-GLOBALS: @"\01l_OBJC_CLASS_RO_$_Test23" = internal global [[RO_T:%.*]] { i32 390,
@interface Test23 { id x; } @end
@implementation Test23 @end