]> granicus.if.org Git - clang/commitdiff
Really protect from infinite loop when there are objc method redeclarations.
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>
Fri, 14 Oct 2011 08:02:31 +0000 (08:02 +0000)
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>
Fri, 14 Oct 2011 08:02:31 +0000 (08:02 +0000)
Serialization part will come later.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@141950 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/DeclObjC.h
lib/AST/DeclObjC.cpp
lib/Sema/SemaDeclObjC.cpp
test/PCH/method-redecls.m

index 849697a954d4e7b42b031d051a5b06147319d679..ea36914eb779311d04000a6501c9c2a9bc91a64d 100644 (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(); }
index 7c1332ab103eb3e4b0a42de166718b334348a912..170cdf43fc425ae0395637e50388cac8974b248b 100644 (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;
 }
 
index bdf492bbc1e39fa5032a7f5679c086b086743075..62b4a7c0cc7730a7cf3b4581b2d1f7f5359fa6c5 100644 (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);
index 14ce3acdfd2228d77427bf7ef6b54371044f56c5..a11bf5aff7dc5b9bf89275a3bf1a323af06d05da 100644 (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