Really protect from infinite loop when there are objc method redeclarations.

Serialization part will come later.

llvm-svn: 141950
This commit is contained in:
Argyrios Kyrtzidis 2011-10-14 08:02:31 +00:00
parent e35b3aae52
commit dcaaa21fbe
4 changed files with 27 additions and 3 deletions

View File

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

View File

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

View File

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

View File

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