]> granicus.if.org Git - clang/commitdiff
Fix potential infinite loop when iterating over redeclarations of an ObjMethodDecl...
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>
Thu, 30 May 2013 18:53:21 +0000 (18:53 +0000)
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>
Thu, 30 May 2013 18:53:21 +0000 (18:53 +0000)
Check for invalid decls in ObjCMethodDecl::getNextRedeclaration(); otherwise if we start from an invalid redeclaration
of an @implementation we would move to the @interface and not reach the original declaration again.

Fixes rdar://14024851

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@182951 91177308-0d34-0410-b5e6-96231b3b80d8

lib/AST/DeclObjC.cpp
lib/Sema/SemaDeclObjC.cpp
test/Sema/warn-documentation.m

index 0291803fd4695546ef72cd2fded22aac9eae01cf..3895a520857c5e6b85c02763f4a2676414b987bd 100644 (file)
@@ -627,23 +627,29 @@ ObjCMethodDecl *ObjCMethodDecl::getNextRedeclaration() {
 
   Decl *CtxD = cast<Decl>(getDeclContext());
 
-  if (ObjCInterfaceDecl *IFD = dyn_cast<ObjCInterfaceDecl>(CtxD)) {
-    if (ObjCImplementationDecl *ImplD = Ctx.getObjCImplementation(IFD))
-      Redecl = ImplD->getMethod(getSelector(), isInstanceMethod());
-
-  } else if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(CtxD)) {
-    if (ObjCCategoryImplDecl *ImplD = Ctx.getObjCImplementation(CD))
-      Redecl = ImplD->getMethod(getSelector(), isInstanceMethod());
-
-  } else if (ObjCImplementationDecl *ImplD =
-               dyn_cast<ObjCImplementationDecl>(CtxD)) {
-    if (ObjCInterfaceDecl *IFD = ImplD->getClassInterface())
-      Redecl = IFD->getMethod(getSelector(), isInstanceMethod());
-
-  } else if (ObjCCategoryImplDecl *CImplD =
-               dyn_cast<ObjCCategoryImplDecl>(CtxD)) {
-    if (ObjCCategoryDecl *CatD = CImplD->getCategoryDecl())
-      Redecl = CatD->getMethod(getSelector(), isInstanceMethod());
+  if (!CtxD->isInvalidDecl()) {
+    if (ObjCInterfaceDecl *IFD = dyn_cast<ObjCInterfaceDecl>(CtxD)) {
+      if (ObjCImplementationDecl *ImplD = Ctx.getObjCImplementation(IFD))
+        if (!ImplD->isInvalidDecl())
+          Redecl = ImplD->getMethod(getSelector(), isInstanceMethod());
+
+    } else if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(CtxD)) {
+      if (ObjCCategoryImplDecl *ImplD = Ctx.getObjCImplementation(CD))
+        if (!ImplD->isInvalidDecl())
+          Redecl = ImplD->getMethod(getSelector(), isInstanceMethod());
+
+    } else if (ObjCImplementationDecl *ImplD =
+                 dyn_cast<ObjCImplementationDecl>(CtxD)) {
+      if (ObjCInterfaceDecl *IFD = ImplD->getClassInterface())
+        if (!IFD->isInvalidDecl())
+          Redecl = IFD->getMethod(getSelector(), isInstanceMethod());
+
+    } else if (ObjCCategoryImplDecl *CImplD =
+                 dyn_cast<ObjCCategoryImplDecl>(CtxD)) {
+      if (ObjCCategoryDecl *CatD = CImplD->getCategoryDecl())
+        if (!CatD->isInvalidDecl())
+          Redecl = CatD->getMethod(getSelector(), isInstanceMethod());
+    }
   }
 
   if (!Redecl && isRedeclaration()) {
index d8517f49f47b9768d8790a015f1bfce4cb6fa266..687cdf114a6a3d6961c6f1fe7291ba7d58600c89 100644 (file)
@@ -935,6 +935,7 @@ Decl *Sema::ActOnStartCategoryImplementation(
         << CatName;
       Diag(CatIDecl->getImplementation()->getLocation(),
            diag::note_previous_definition);
+      CDecl->setInvalidDecl();
     } else {
       CatIDecl->setImplementation(CDecl);
       // Warn on implementating category of deprecated class under 
@@ -1056,6 +1057,7 @@ Decl *Sema::ActOnStartClassImplementation(
     Diag(ClassLoc, diag::err_dup_implementation_class) << ClassName;
     Diag(IDecl->getImplementation()->getLocation(),
          diag::note_previous_definition);
+    IMPDecl->setInvalidDecl();
   } else { // add it to the list.
     IDecl->setImplementation(IMPDecl);
     PushOnScopeChains(IMPDecl, TUScope);
index 1d3114617ebbd719e74965d8c117fa051d928697..17dd92e6eba48f77ee6d76eb1e341becdbbf5114 100644 (file)
@@ -203,3 +203,15 @@ int FooBar();
 @interface Asset : NSObject
 @end
 
+// rdar://14024851 Check that this does not enter an infinite loop
+@interface rdar14024851
+-(void)meth; // expected-note {{declared here}}
+@end
+
+@implementation rdar14024851 // expected-warning {{method definition for 'meth' not found}} expected-note {{previous definition}}
+@end
+
+@implementation rdar14024851 // expected-error {{reimplementation}}
+/// \brief comment
+-(void)meth {}
+@end