forked from OSchip/llvm-project
Really protect from infinite loop when there are objc method redeclarations.
Serialization part will come later. llvm-svn: 141950
This commit is contained in:
parent
e35b3aae52
commit
dcaaa21fbe
|
@ -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(); }
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue