Keep track of objc method redeclarations in the same interface.

Avoid possible infinite loop when iterating over an ObjCMethod's redeclarations.

llvm-svn: 141946
This commit is contained in:
Argyrios Kyrtzidis 2011-10-14 06:48:06 +00:00
parent 6524dd33be
commit c5e829cad2
4 changed files with 41 additions and 1 deletions

View File

@ -151,6 +151,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;
@ -1586,6 +1590,21 @@ public:
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);
/// \brief Get the copy initialization expression of VarDecl,or NULL if

View File

@ -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)) {

View File

@ -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);

View File

@ -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