From: Argyrios Kyrtzidis Date: Thu, 30 May 2013 18:53:21 +0000 (+0000) Subject: Fix potential infinite loop when iterating over redeclarations of an ObjMethodDecl... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=df08c4b371522025d1d3aec4992fb0f27d7c4571;p=clang Fix potential infinite loop when iterating over redeclarations of an ObjMethodDecl, resulting from invalid code. 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 --- diff --git a/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp index 0291803fd4..3895a52085 100644 --- a/lib/AST/DeclObjC.cpp +++ b/lib/AST/DeclObjC.cpp @@ -627,23 +627,29 @@ ObjCMethodDecl *ObjCMethodDecl::getNextRedeclaration() { Decl *CtxD = cast(getDeclContext()); - if (ObjCInterfaceDecl *IFD = dyn_cast(CtxD)) { - if (ObjCImplementationDecl *ImplD = Ctx.getObjCImplementation(IFD)) - Redecl = ImplD->getMethod(getSelector(), isInstanceMethod()); - - } else if (ObjCCategoryDecl *CD = dyn_cast(CtxD)) { - if (ObjCCategoryImplDecl *ImplD = Ctx.getObjCImplementation(CD)) - Redecl = ImplD->getMethod(getSelector(), isInstanceMethod()); - - } else if (ObjCImplementationDecl *ImplD = - dyn_cast(CtxD)) { - if (ObjCInterfaceDecl *IFD = ImplD->getClassInterface()) - Redecl = IFD->getMethod(getSelector(), isInstanceMethod()); - - } else if (ObjCCategoryImplDecl *CImplD = - dyn_cast(CtxD)) { - if (ObjCCategoryDecl *CatD = CImplD->getCategoryDecl()) - Redecl = CatD->getMethod(getSelector(), isInstanceMethod()); + if (!CtxD->isInvalidDecl()) { + if (ObjCInterfaceDecl *IFD = dyn_cast(CtxD)) { + if (ObjCImplementationDecl *ImplD = Ctx.getObjCImplementation(IFD)) + if (!ImplD->isInvalidDecl()) + Redecl = ImplD->getMethod(getSelector(), isInstanceMethod()); + + } else if (ObjCCategoryDecl *CD = dyn_cast(CtxD)) { + if (ObjCCategoryImplDecl *ImplD = Ctx.getObjCImplementation(CD)) + if (!ImplD->isInvalidDecl()) + Redecl = ImplD->getMethod(getSelector(), isInstanceMethod()); + + } else if (ObjCImplementationDecl *ImplD = + dyn_cast(CtxD)) { + if (ObjCInterfaceDecl *IFD = ImplD->getClassInterface()) + if (!IFD->isInvalidDecl()) + Redecl = IFD->getMethod(getSelector(), isInstanceMethod()); + + } else if (ObjCCategoryImplDecl *CImplD = + dyn_cast(CtxD)) { + if (ObjCCategoryDecl *CatD = CImplD->getCategoryDecl()) + if (!CatD->isInvalidDecl()) + Redecl = CatD->getMethod(getSelector(), isInstanceMethod()); + } } if (!Redecl && isRedeclaration()) { diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index d8517f49f4..687cdf114a 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -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); diff --git a/test/Sema/warn-documentation.m b/test/Sema/warn-documentation.m index 1d3114617e..17dd92e6eb 100644 --- a/test/Sema/warn-documentation.m +++ b/test/Sema/warn-documentation.m @@ -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