diff options
author | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2011-10-14 06:48:06 +0000 |
---|---|---|
committer | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2011-10-14 06:48:06 +0000 |
commit | b40034c2e580ab3b08de9dfb738d8e5d8ef79136 (patch) | |
tree | 7135179f3044eb13380b0fec707f8b25fc56bd38 | |
parent | 905c45f15a25598620d19160c139c6b785aeea89 (diff) |
Keep track of objc method redeclarations in the same interface.
Avoid possible infinite loop when iterating over an ObjCMethod's redeclarations.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@141946 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/AST/ASTContext.h | 19 | ||||
-rw-r--r-- | lib/AST/DeclObjC.cpp | 6 | ||||
-rw-r--r-- | lib/Sema/SemaDeclObjC.cpp | 4 | ||||
-rw-r--r-- | test/PCH/method-redecls.m | 13 |
4 files changed, 41 insertions, 1 deletions
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 09defdb31e..05311ff0bf 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -150,6 +150,10 @@ class ASTContext : public llvm::RefCountedBase<ASTContext> { /// \brief Mapping from ObjCContainers to their ObjCImplementations. llvm::DenseMap<ObjCContainerDecl*, ObjCImplDecl*> ObjCImpls; + + /// \brief Mapping from ObjCMethod to its duplicate declaration in the same + /// interface. + llvm::DenseMap<const ObjCMethodDecl*,const ObjCMethodDecl*> ObjCMethodRedecls; /// \brief Mapping from __block VarDecls to their copy initialization expr. llvm::DenseMap<const VarDecl*, Expr*> BlockVarCopyInits; @@ -1585,6 +1589,21 @@ public: /// \brief Set the implementation of ObjCCategoryDecl. void setObjCImplementation(ObjCCategoryDecl *CatD, ObjCCategoryImplDecl *ImplD); + + /// \brief Get the duplicate declaration of a ObjCMethod in the same + /// interface, or null if non exists. + const ObjCMethodDecl *getObjCMethodRedeclaration(ObjCMethodDecl *MD) const { + llvm::DenseMap<const ObjCMethodDecl*, const ObjCMethodDecl*>::const_iterator + I = ObjCMethodRedecls.find(MD); + if (I == ObjCMethodRedecls.end()) + return 0; + return I->second; + } + + void setObjCMethodRedeclaration(const ObjCMethodDecl *MD, + const ObjCMethodDecl *Redecl) { + ObjCMethodRedecls[MD] = Redecl; + } /// \brief Set the copy inialization expression of a block var decl. void setBlockVarCopyInits(VarDecl*VD, Expr* Init); diff --git a/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp index 48fbbe0c2b..7c1332ab10 100644 --- a/lib/AST/DeclObjC.cpp +++ b/lib/AST/DeclObjC.cpp @@ -392,7 +392,11 @@ void ObjCMethodDecl::setMethodParams(ASTContext &C, /// Otherwise it will return itself. ObjCMethodDecl *ObjCMethodDecl::getNextRedeclaration() { ASTContext &Ctx = getASTContext(); - ObjCMethodDecl *Redecl = 0; + ObjCMethodDecl *Redecl = + const_cast<ObjCMethodDecl*>(Ctx.getObjCMethodRedeclaration(this)); + if (Redecl) + return Redecl; + Decl *CtxD = cast<Decl>(getDeclContext()); if (ObjCInterfaceDecl *IFD = dyn_cast<ObjCInterfaceDecl>(CtxD)) { diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index 82b5b17fa4..bdf492bbc1 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -2167,6 +2167,8 @@ void Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, Diag(PrevMethod->getLocation(), diag::note_previous_declaration); Method->setInvalidDecl(); } else { + if (PrevMethod) + Context.setObjCMethodRedeclaration(PrevMethod, Method); InsMap[Method->getSelector()] = Method; /// The following allows us to typecheck messages to "id". AddInstanceMethodToGlobalPool(Method); @@ -2186,6 +2188,8 @@ void Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, Diag(PrevMethod->getLocation(), diag::note_previous_declaration); Method->setInvalidDecl(); } else { + if (PrevMethod) + Context.setObjCMethodRedeclaration(PrevMethod, Method); 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 new file mode 100644 index 0000000000..14ce3acdfd --- /dev/null +++ b/test/PCH/method-redecls.m @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -x objective-c -emit-pch -o %t + +// Avoid infinite loop because of method redeclarations. + +@interface Foo +-(void)meth; +-(void)meth; +-(void)meth; +@end + +@implementation Foo +-(void)meth { } +@end |