]> granicus.if.org Git - clang/commitdiff
don't crash if class is using itself as its super class.
authorFariborz Jahanian <fjahanian@apple.com>
Thu, 9 Jul 2009 22:08:26 +0000 (22:08 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Thu, 9 Jul 2009 22:08:26 +0000 (22:08 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@75178 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaDeclObjC.cpp
test/SemaObjC/undef-superclass-1.m

index 7078530dc6f396176b32bd9f3f3e3a7dcb7210ce..2a492fb14d7902fd262c5cee2fb115ef5d73de9d 100644 (file)
@@ -145,6 +145,8 @@ def err_duplicate_class_def : Error<
   "duplicate interface definition for class %0">;
 def err_undef_superclass : Error<
   "cannot find interface declaration for %0, superclass of %1">;
+def err_recursive_superclass : Error<
+  "trying to recursively use %0 as superclass of %1">;
 def warn_previous_alias_decl : Warning<"previously declared alias is ignored">;
 def err_conflicting_aliasing_type : Error<"conflicting types for alias %0">;
 def warn_undef_interface : Warning<"cannot find interface declaration for %0">;
index 5cf48d6da0c861457e755dce1fb47e3dd5ac2a4e..62d28f326fbb5af80070ce8d53ee4479138edfc6 100644 (file)
@@ -124,48 +124,54 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
   if (SuperName) {
     // Check if a different kind of symbol declared in this scope.
     PrevDecl = LookupName(TUScope, SuperName, LookupOrdinaryName);
+    if (PrevDecl == IDecl) {
+      Diag(SuperLoc, diag::err_recursive_superclass)
+        << SuperName << ClassName << SourceRange(AtInterfaceLoc, ClassLoc);
+      IDecl->setLocEnd(ClassLoc);
+    }
+    else {
+      ObjCInterfaceDecl *SuperClassDecl = 
+                                dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl);
 
-    ObjCInterfaceDecl *SuperClassDecl = 
-                                  dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl);
-
-    // Diagnose classes that inherit from deprecated classes.
-    if (SuperClassDecl)
-      (void)DiagnoseUseOfDecl(SuperClassDecl, SuperLoc);
+      // Diagnose classes that inherit from deprecated classes.
+      if (SuperClassDecl)
+        (void)DiagnoseUseOfDecl(SuperClassDecl, SuperLoc);
     
-    if (PrevDecl && SuperClassDecl == 0) {
-      // The previous declaration was not a class decl. Check if we have a
-      // typedef. If we do, get the underlying class type.
-      if (const TypedefDecl *TDecl = dyn_cast_or_null<TypedefDecl>(PrevDecl)) {
-        QualType T = TDecl->getUnderlyingType();
-        if (T->isObjCInterfaceType()) {
-          if (NamedDecl *IDecl = T->getAsObjCInterfaceType()->getDecl())
-            SuperClassDecl = dyn_cast<ObjCInterfaceDecl>(IDecl);
+      if (PrevDecl && SuperClassDecl == 0) {
+        // The previous declaration was not a class decl. Check if we have a
+        // typedef. If we do, get the underlying class type.
+        if (const TypedefDecl *TDecl = dyn_cast_or_null<TypedefDecl>(PrevDecl)) {
+          QualType T = TDecl->getUnderlyingType();
+          if (T->isObjCInterfaceType()) {
+            if (NamedDecl *IDecl = T->getAsObjCInterfaceType()->getDecl())
+              SuperClassDecl = dyn_cast<ObjCInterfaceDecl>(IDecl);
+          }
         }
-      }
       
-      // This handles the following case:
-      //
-      // typedef int SuperClass;
-      // @interface MyClass : SuperClass {} @end
-      //
-      if (!SuperClassDecl) {
-        Diag(SuperLoc, diag::err_redefinition_different_kind) << SuperName;
-        Diag(PrevDecl->getLocation(), diag::note_previous_definition);
+        // This handles the following case:
+        //
+        // typedef int SuperClass;
+        // @interface MyClass : SuperClass {} @end
+        //
+        if (!SuperClassDecl) {
+          Diag(SuperLoc, diag::err_redefinition_different_kind) << SuperName;
+          Diag(PrevDecl->getLocation(), diag::note_previous_definition);
+        }
       }
+  
+      if (!dyn_cast_or_null<TypedefDecl>(PrevDecl)) {
+        if (!SuperClassDecl)
+          Diag(SuperLoc, diag::err_undef_superclass)
+            << SuperName << ClassName << SourceRange(AtInterfaceLoc, ClassLoc);
+        else if (SuperClassDecl->isForwardDecl())
+          Diag(SuperLoc, diag::err_undef_superclass)
+            << SuperClassDecl->getDeclName() << ClassName
+            << SourceRange(AtInterfaceLoc, ClassLoc);
+      }
+      IDecl->setSuperClass(SuperClassDecl);
+      IDecl->setSuperClassLoc(SuperLoc);
+      IDecl->setLocEnd(SuperLoc);
     }
-    
-    if (!dyn_cast_or_null<TypedefDecl>(PrevDecl)) {
-      if (!SuperClassDecl)
-        Diag(SuperLoc, diag::err_undef_superclass)
-          << SuperName << ClassName << SourceRange(AtInterfaceLoc, ClassLoc);
-      else if (SuperClassDecl->isForwardDecl())
-        Diag(SuperLoc, diag::err_undef_superclass)
-          << SuperClassDecl->getDeclName() << ClassName
-          << SourceRange(AtInterfaceLoc, ClassLoc);
-    }
-    IDecl->setSuperClass(SuperClassDecl);
-    IDecl->setSuperClassLoc(SuperLoc);
-    IDecl->setLocEnd(SuperLoc);
   } else { // we have a root class.
     IDecl->setLocEnd(ClassLoc);
   }
index 0d670f8c08092b0fab226c646f4ff3658c397e02..cb15dc39a3dcb6f0f0da56f22fc88fa7344309a9 100644 (file)
     [super dealloc]; // expected-error {{no super class declared in @interface for 'SUPER'}}
 }
 @end
+
+@interface RecursiveClass : RecursiveClass // expected-error {{trying to recursively use 'RecursiveClass' as superclass of 'RecursiveClass'}}
+@end
+
+@implementation RecursiveClass
+@end
+