forked from OSchip/llvm-project
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:
parent
6524dd33be
commit
c5e829cad2
|
@ -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
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
Loading…
Reference in New Issue