From: Argyrios Kyrtzidis Date: Fri, 14 Oct 2011 08:02:31 +0000 (+0000) Subject: Really protect from infinite loop when there are objc method redeclarations. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=3a919e7110407ae7609bb6edc57aac16a5990661;p=clang Really protect from infinite loop when there are objc method redeclarations. Serialization part will come later. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@141950 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h index 849697a954..ea36914eb7 100644 --- a/include/clang/AST/DeclObjC.h +++ b/include/clang/AST/DeclObjC.h @@ -128,6 +128,9 @@ private: // Method has a definition. unsigned IsDefined : 1; + // Method redeclaration in the same interface. + unsigned IsRedeclaration : 1; + // NOTE: VC++ treats enums as signed, avoid using ImplementationControl enum /// @required/@optional unsigned DeclImplementation : 2; @@ -220,7 +223,7 @@ private: DeclContext(ObjCMethod), Family(InvalidObjCMethodFamily), IsInstance(isInstance), IsVariadic(isVariadic), IsSynthesized(isSynthesized), - IsDefined(isDefined), + IsDefined(isDefined), IsRedeclaration(0), DeclImplementation(impControl), objcDeclQualifier(OBJC_TQ_None), RelatedResultType(HasRelatedResultType), SelLocsKind(SelLoc_StandardNoSpace), @@ -267,6 +270,10 @@ public: /// \brief Note whether this method has a related result type. void SetRelatedResultType(bool RRT = true) { RelatedResultType = RRT; } + + /// \brief True if this is a method redeclaration in the same interface. + bool isRedeclaration() const { return IsRedeclaration; } + void setAsRedeclaration(const ObjCMethodDecl *PrevMethod); // Location information, modeled after the Stmt API. SourceLocation getLocStart() const { return getLocation(); } diff --git a/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp index 7c1332ab10..170cdf43fc 100644 --- a/lib/AST/DeclObjC.cpp +++ b/lib/AST/DeclObjC.cpp @@ -351,6 +351,12 @@ ObjCMethodDecl *ObjCMethodDecl::Create(ASTContext &C, HasRelatedResultType); } +void ObjCMethodDecl::setAsRedeclaration(const ObjCMethodDecl *PrevMethod) { + assert(PrevMethod); + getASTContext().setObjCMethodRedeclaration(PrevMethod, this); + IsRedeclaration = true; +} + void ObjCMethodDecl::setParamsAndSelLocs(ASTContext &C, ArrayRef Params, ArrayRef SelLocs) { @@ -418,6 +424,12 @@ ObjCMethodDecl *ObjCMethodDecl::getNextRedeclaration() { Redecl = CatD->getMethod(getSelector(), isInstanceMethod()); } + if (!Redecl && isRedeclaration()) { + // This is the last redeclaration, go back to the first method. + return cast(CtxD)->getMethod(getSelector(), + isInstanceMethod()); + } + return Redecl ? Redecl : this; } diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index bdf492bbc1..62b4a7c0cc 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -2168,7 +2168,7 @@ void Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, Method->setInvalidDecl(); } else { if (PrevMethod) - Context.setObjCMethodRedeclaration(PrevMethod, Method); + Method->setAsRedeclaration(PrevMethod); InsMap[Method->getSelector()] = Method; /// The following allows us to typecheck messages to "id". AddInstanceMethodToGlobalPool(Method); @@ -2189,7 +2189,7 @@ void Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, Method->setInvalidDecl(); } else { if (PrevMethod) - Context.setObjCMethodRedeclaration(PrevMethod, Method); + Method->setAsRedeclaration(PrevMethod); ClsMap[Method->getSelector()] = Method; /// The following allows us to typecheck messages to "Class". AddFactoryMethodToGlobalPool(Method); diff --git a/test/PCH/method-redecls.m b/test/PCH/method-redecls.m index 14ce3acdfd..a11bf5aff7 100644 --- a/test/PCH/method-redecls.m +++ b/test/PCH/method-redecls.m @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -x objective-c -emit-pch -o %t +// RUN: %clang_cc1 -x objective-c -emit-pch -o %t -D IMPL // Avoid infinite loop because of method redeclarations. @@ -8,6 +9,10 @@ -(void)meth; @end +#ifdef IMPL + @implementation Foo -(void)meth { } @end + +#endif