r196476 - [objc] If an interface has no initializer marked as designated and introduces at least one new initializer,

Argyrios Kyrtzidis akyrtzi at gmail.com
Wed Dec 4 23:07:03 PST 2013


Author: akirtzidis
Date: Thu Dec  5 01:07:03 2013
New Revision: 196476

URL: http://llvm.org/viewvc/llvm-project?rev=196476&view=rev
Log:
[objc] If an interface has no initializer marked as designated and introduces at least one new initializer,
don't assume that it inherits the designated initializers from the super class.

If the assumption was wrong because a new initializer was a designated one that was not marked as such,
we will emit misleading warnings for subclasses of the interface.

Modified:
    cfe/trunk/include/clang/AST/DeclObjC.h
    cfe/trunk/lib/AST/DeclObjC.cpp
    cfe/trunk/test/SemaObjC/attr-designated-init.m

Modified: cfe/trunk/include/clang/AST/DeclObjC.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclObjC.h?rev=196476&r1=196475&r2=196476&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclObjC.h (original)
+++ cfe/trunk/include/clang/AST/DeclObjC.h Thu Dec  5 01:07:03 2013
@@ -678,6 +678,18 @@ class ObjCInterfaceDecl : public ObjCCon
     /// 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;
     
@@ -689,7 +701,8 @@ class ObjCInterfaceDecl : public ObjCCon
     DefinitionData() : Definition(), SuperClass(), CategoryList(), IvarList(), 
                        ExternallyCompleted(),
                        IvarListMissingImplementation(true),
-                       HasDesignatedInitializers() { }
+                       HasDesignatedInitializers(),
+                       InheritedDesignatedInitializers(IDI_Unknown) { }
   };
 
   ObjCInterfaceDecl(DeclContext *DC, SourceLocation atLoc, IdentifierInfo *Id,
@@ -1273,6 +1286,10 @@ public:
   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

Modified: cfe/trunk/lib/AST/DeclObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclObjC.cpp?rev=196476&r1=196475&r2=196476&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclObjC.cpp (original)
+++ cfe/trunk/lib/AST/DeclObjC.cpp Thu Dec  5 01:07:03 2013
@@ -380,21 +380,61 @@ void ObjCInterfaceDecl::mergeClassExtens
   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;
@@ -409,13 +449,7 @@ bool ObjCInterfaceDecl::isDesignatedInit
   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;
 

Modified: cfe/trunk/test/SemaObjC/attr-designated-init.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/attr-designated-init.m?rev=196476&r1=196475&r2=196476&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/attr-designated-init.m (original)
+++ cfe/trunk/test/SemaObjC/attr-designated-init.m Thu Dec  5 01:07:03 2013
@@ -34,7 +34,7 @@ __attribute__((objc_root_class))
 
 __attribute__((objc_root_class))
 @interface B1
--(id)initB1 NS_DESIGNATED_INITIALIZER; // expected-note 4 {{method marked as designated initializer of the class here}}
+-(id)initB1 NS_DESIGNATED_INITIALIZER; // expected-note 5 {{method marked as designated initializer of the class here}}
 -(id)initB2;
 -(id)initB3 NS_DESIGNATED_INITIALIZER; // expected-note 3 {{method marked as designated initializer of the class here}}
 @end
@@ -177,3 +177,29 @@ __attribute__((objc_root_class))
   return [s initS1];
 }
 @end
+
+ at interface SS4 : S4
+-(id)initB1;
+ at end
+
+ at implementation SS4
+-(id)initB1 { // expected-warning {{designated initializer missing a 'super' call to a designated initializer of the super class}}
+  return 0;
+}
+ at end
+
+ at interface S7 : B1
+-(id)initB1;
+-(id)initB3;
+-(id)initNewOne;
+ at end
+
+ at interface SS7 : S7
+-(id)initB1;
+ at end
+
+ at implementation SS7
+-(id)initB1 {
+  return 0;
+}
+ at end





More information about the cfe-commits mailing list