diff options
author | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2011-10-14 08:02:31 +0000 |
---|---|---|
committer | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2011-10-14 08:02:31 +0000 |
commit | 3a919e7110407ae7609bb6edc57aac16a5990661 (patch) | |
tree | 6e270fb759729dcbc37f2a8c6606364d40338d1a | |
parent | 1e2b3d7c6117d663b69d6a71ba8cb9c616e3ee7f (diff) |
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
-rw-r--r-- | include/clang/AST/DeclObjC.h | 9 | ||||
-rw-r--r-- | lib/AST/DeclObjC.cpp | 12 | ||||
-rw-r--r-- | lib/Sema/SemaDeclObjC.cpp | 4 | ||||
-rw-r--r-- | test/PCH/method-redecls.m | 5 |
4 files changed, 27 insertions, 3 deletions
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<ParmVarDecl*> Params, ArrayRef<SourceLocation> 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<ObjCContainerDecl>(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 |