/// marked with the 'objc_designated_initializer' attribute.
bool HasDesignatedInitializers : 1;
+ enum InheritedDesignatedInitializersState {
+ /// We didn't calculated whether the designated initializers should be
+ /// inherited or not.
+ IDI_Unknown = 0,
+ /// Designated initializers are inherited for the super class.
+ IDI_Inherited = 1,
+ /// The class does not inherit designated initializers.
+ IDI_NotInherited = 2
+ };
+ /// One of the \c InheritedDesignatedInitializersState enumeratos.
+ mutable unsigned InheritedDesignatedInitializers : 2;
+
/// \brief The location of the superclass, if any.
SourceLocation SuperClassLoc;
DefinitionData() : Definition(), SuperClass(), CategoryList(), IvarList(),
ExternallyCompleted(),
IvarListMissingImplementation(true),
- HasDesignatedInitializers() { }
+ HasDesignatedInitializers(),
+ InheritedDesignatedInitializers(IDI_Unknown) { }
};
ObjCInterfaceDecl(DeclContext *DC, SourceLocation atLoc, IdentifierInfo *Id,
friend class ASTReader;
friend class ASTDeclReader;
friend class ASTDeclWriter;
+
+private:
+ const ObjCInterfaceDecl *findInterfaceWithDesignatedInitializers() const;
+ bool inheritsDesignatedInitializers() const;
};
/// ObjCIvarDecl - Represents an ObjC instance variable. In general, ObjC
data().AllReferencedProtocols.set(ProtocolRefs.data(), ProtocolRefs.size(),C);
}
-void ObjCInterfaceDecl::getDesignatedInitializers(
- llvm::SmallVectorImpl<const ObjCMethodDecl *> &Methods) const {
- assert(hasDefinition());
- if (data().ExternallyCompleted)
- LoadExternalDefinition();
-
+const ObjCInterfaceDecl *
+ObjCInterfaceDecl::findInterfaceWithDesignatedInitializers() const {
const ObjCInterfaceDecl *IFace = this;
while (IFace) {
- if (IFace->data().HasDesignatedInitializers)
+ if (IFace->hasDesignatedInitializers())
+ return IFace;
+ if (!IFace->inheritsDesignatedInitializers())
break;
IFace = IFace->getSuperClass();
}
+ return 0;
+}
+bool ObjCInterfaceDecl::inheritsDesignatedInitializers() const {
+ switch (data().InheritedDesignatedInitializers) {
+ case DefinitionData::IDI_Inherited:
+ return true;
+ case DefinitionData::IDI_NotInherited:
+ return false;
+ case DefinitionData::IDI_Unknown: {
+ bool isIntroducingInitializers = false;
+ for (instmeth_iterator I = instmeth_begin(),
+ E = instmeth_end(); I != E; ++I) {
+ const ObjCMethodDecl *MD = *I;
+ if (MD->getMethodFamily() == OMF_init && !MD->isOverriding()) {
+ isIntroducingInitializers = true;
+ break;
+ }
+ }
+ // If the class introduced initializers we conservatively assume that we
+ // don't know if any of them is a designated initializer to avoid possible
+ // misleading warnings.
+ if (isIntroducingInitializers) {
+ data().InheritedDesignatedInitializers = DefinitionData::IDI_NotInherited;
+ return false;
+ } else {
+ data().InheritedDesignatedInitializers = DefinitionData::IDI_Inherited;
+ return true;
+ }
+ }
+ }
+
+ llvm_unreachable("unexpected InheritedDesignatedInitializers value");
+}
+
+void ObjCInterfaceDecl::getDesignatedInitializers(
+ llvm::SmallVectorImpl<const ObjCMethodDecl *> &Methods) const {
+ assert(hasDefinition());
+ if (data().ExternallyCompleted)
+ LoadExternalDefinition();
+
+ const ObjCInterfaceDecl *IFace= findInterfaceWithDesignatedInitializers();
if (!IFace)
return;
+
for (instmeth_iterator I = IFace->instmeth_begin(),
E = IFace->instmeth_end(); I != E; ++I) {
const ObjCMethodDecl *MD = *I;
if (data().ExternallyCompleted)
LoadExternalDefinition();
- const ObjCInterfaceDecl *IFace = this;
- while (IFace) {
- if (IFace->data().HasDesignatedInitializers)
- break;
- IFace = IFace->getSuperClass();
- }
-
+ const ObjCInterfaceDecl *IFace= findInterfaceWithDesignatedInitializers();
if (!IFace)
return false;