summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>2011-10-14 08:02:31 +0000
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>2011-10-14 08:02:31 +0000
commit3a919e7110407ae7609bb6edc57aac16a5990661 (patch)
tree6e270fb759729dcbc37f2a8c6606364d40338d1a
parent1e2b3d7c6117d663b69d6a71ba8cb9c616e3ee7f (diff)
Really protect from infinite loop when there are objc method redeclarations.
Serialization part will come later. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@141950 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/AST/DeclObjC.h9
-rw-r--r--lib/AST/DeclObjC.cpp12
-rw-r--r--lib/Sema/SemaDeclObjC.cpp4
-rw-r--r--test/PCH/method-redecls.m5
4 files changed, 27 insertions, 3 deletions
diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h
index 849697a954..ea36914eb7 100644
--- a/include/clang/AST/DeclObjC.h
+++ b/include/clang/AST/DeclObjC.h
@@ -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(); }
diff --git a/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp
index 7c1332ab10..170cdf43fc 100644
--- a/lib/AST/DeclObjC.cpp
+++ b/lib/AST/DeclObjC.cpp
@@ -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;
}
diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp
index bdf492bbc1..62b4a7c0cc 100644
--- a/lib/Sema/SemaDeclObjC.cpp
+++ b/lib/Sema/SemaDeclObjC.cpp
@@ -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);
diff --git a/test/PCH/method-redecls.m b/test/PCH/method-redecls.m
index 14ce3acdfd..a11bf5aff7 100644
--- a/test/PCH/method-redecls.m
+++ b/test/PCH/method-redecls.m
@@ -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