]> granicus.if.org Git - clang/commitdiff
Use Sema::RequireCompleteType to check for the completeness of
authorDouglas Gregor <dgregor@apple.com>
Mon, 14 Nov 2011 22:10:01 +0000 (22:10 +0000)
committerDouglas Gregor <dgregor@apple.com>
Mon, 14 Nov 2011 22:10:01 +0000 (22:10 +0000)
Objective-C classes. This has two purposes: to consistently provide
"forward declaration here" notes when we hit an incomplete type, and
to give LLDB a chance to complete the type.

RequireCompleteType bits from Sean Callanan!

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

18 files changed:
include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaDeclObjC.cpp
lib/Sema/SemaExprObjC.cpp
lib/Sema/SemaStmt.cpp
lib/Sema/SemaType.cpp
test/Analysis/rdar-6540084.m
test/SemaObjC/arc.m
test/SemaObjC/category-1.m
test/SemaObjC/class-impl-1.m
test/SemaObjC/class-proto-1.m
test/SemaObjC/exprs.m
test/SemaObjC/forward-class-1.m
test/SemaObjC/forward-class-receiver.m
test/SemaObjC/property-9.m
test/SemaObjC/property-missing.m
test/SemaObjC/sizeof-interface.m
test/SemaObjC/special-dep-unavail-warning.m
test/SemaObjC/undef-superclass-1.m

index 312ea824588ce10bef38420883230c2db9ce6284..3d9b5b9214768258cd3078f8093b7b5ad5dd8dcd 100644 (file)
@@ -373,6 +373,8 @@ def warn_property_attribute : Warning<
 def warn_property_types_are_incompatible : Warning<
   "property type %0 is incompatible with type %1 inherited from %2">;
 def err_undef_interface : Error<"cannot find interface declaration for %0">;
+def err_category_forward_interface : Error<
+  "cannot define %select{category|class extension}0 for undefined class %1">;
 def err_class_extension_after_impl : Error<
   "cannot declare class extension for %0 after class implementation">;
 def note_implementation_declared : Note<
@@ -3617,7 +3619,7 @@ def err_property_not_as_forward_class : Error<
   "property %0 refers to an incomplete Objective-C class %1 "
   "(with no @interface available)">;
 def note_forward_class : Note<
-  "forward class is declared here">;
+  "forward declaration of class here">;
 def err_duplicate_property : Error<
   "property has a previous declaration">;
 def ext_gnu_void_ptr : Extension<
index fe9a7841cfd07adf76f7fc657e55704893e19cc1..f4e2fb320538b8079294d0e28c1820ce04a11e11 100644 (file)
@@ -463,11 +463,12 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
         if (!SuperClassDecl)
           Diag(SuperLoc, diag::err_undef_superclass)
             << SuperName << ClassName << SourceRange(AtInterfaceLoc, ClassLoc);
-        else if (SuperClassDecl->isForwardDecl()) {
-          Diag(SuperLoc, diag::err_forward_superclass)
-            << SuperClassDecl->getDeclName() << ClassName
-            << SourceRange(AtInterfaceLoc, ClassLoc);
-          Diag(SuperClassDecl->getLocation(), diag::note_forward_class);
+        else if (RequireCompleteType(SuperLoc, 
+                   Context.getObjCInterfaceType(SuperClassDecl),
+                   PDiag(diag::err_forward_superclass)
+                     << SuperClassDecl->getDeclName() 
+                     << ClassName
+                   << SourceRange(AtInterfaceLoc, ClassLoc))) {
           SuperClassDecl = 0;
         }
       }
@@ -746,14 +747,20 @@ ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc,
   ObjCInterfaceDecl *IDecl = getObjCInterfaceDecl(ClassName, ClassLoc, true);
 
   /// Check that class of this category is already completely declared.
-  if (!IDecl || IDecl->isForwardDecl()) {
+
+  if (!IDecl 
+      || RequireCompleteType(ClassLoc, Context.getObjCInterfaceType(IDecl),
+                             PDiag(diag::err_category_forward_interface)
+                               << (CategoryName == 0))) {
     // Create an invalid ObjCCategoryDecl to serve as context for
     // the enclosing method declarations.  We mark the decl invalid
     // to make it clear that this isn't a valid AST.
     CDecl = ObjCCategoryDecl::Create(Context, CurContext, AtInterfaceLoc,
                                      ClassLoc, CategoryLoc, CategoryName,IDecl);
     CDecl->setInvalidDecl();
-    Diag(ClassLoc, diag::err_undef_interface) << ClassName;
+        
+    if (!IDecl)
+      Diag(ClassLoc, diag::err_undef_interface) << ClassName;
     return ActOnObjCContainerStartDefinition(CDecl);
   }
 
@@ -820,9 +827,12 @@ Decl *Sema::ActOnStartCategoryImplementation(
     ObjCCategoryImplDecl::Create(Context, CurContext, CatName, IDecl,
                                  ClassLoc, AtCatImplLoc);
   /// Check that class of this category is already completely declared.
-  if (!IDecl || IDecl->isForwardDecl()) {
+  if (!IDecl) {
     Diag(ClassLoc, diag::err_undef_interface) << ClassName;
     CDecl->setInvalidDecl();
+  } else if (RequireCompleteType(ClassLoc, Context.getObjCInterfaceType(IDecl),
+                                 diag::err_undef_interface)) {
+    CDecl->setInvalidDecl();
   }
 
   // FIXME: PushOnScopeChains?
@@ -867,11 +877,9 @@ Decl *Sema::ActOnStartClassImplementation(
     Diag(ClassLoc, diag::err_redefinition_different_kind) << ClassName;
     Diag(PrevDecl->getLocation(), diag::note_previous_definition);
   } else if ((IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl))) {
-    // If this is a forward declaration of an interface, warn.
-    if (IDecl->isForwardDecl()) {
-      Diag(ClassLoc, diag::warn_undef_interface) << ClassName;
+    if (RequireCompleteType(ClassLoc, Context.getObjCInterfaceType(IDecl),
+                            diag::warn_undef_interface))
       IDecl = 0;
-    }
   } else {
     // We did not find anything with the name ClassName; try to correct for 
     // typos in the class name.
index 28a5a43055792c6ffd77b36e638c312e216f2236..c4f01c093a7b412ec6d0546f62fb1bb49260ad0a 100644 (file)
@@ -591,13 +591,13 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT,
   }
   
   IdentifierInfo *Member = MemberName.getAsIdentifierInfo();
-
-  if (IFace->isForwardDecl()) {
-    Diag(MemberLoc, diag::err_property_not_found_forward_class)
-         << MemberName << QualType(OPT, 0);
-    Diag(IFace->getLocation(), diag::note_forward_class);
+  SourceRange BaseRange = Super? SourceRange(SuperLoc)
+                               : BaseExpr->getSourceRange();
+  if (RequireCompleteType(MemberLoc, OPT->getPointeeType(), 
+                          PDiag(diag::err_property_not_found_forward_class)
+                            << MemberName << BaseRange))
     return ExprError();
-  }
+  
   // Search for a declared property first.
   if (ObjCPropertyDecl *PD = IFace->FindPropertyDeclaration(Member)) {
     // Check whether we can reference this property.
@@ -722,14 +722,10 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT,
     QualType T = Ivar->getType();
     if (const ObjCObjectPointerType * OBJPT = 
         T->getAsObjCInterfacePointerType()) {
-      const ObjCInterfaceType *IFaceT = OBJPT->getInterfaceType();
-      if (ObjCInterfaceDecl *IFace = IFaceT->getDecl())
-        if (IFace->isForwardDecl()) {
-          Diag(MemberLoc, diag::err_property_not_as_forward_class)
-          << MemberName << IFace;
-          Diag(IFace->getLocation(), diag::note_forward_class);
-          return ExprError();
-        }
+      if (RequireCompleteType(MemberLoc, OBJPT->getPointeeType(), 
+                              PDiag(diag::err_property_not_as_forward_class)
+                                << MemberName << BaseExpr->getSourceRange()))
+        return ExprError();
     }
     Diag(MemberLoc, 
          diag::err_ivar_access_using_property_syntax_suggest)
@@ -1083,13 +1079,14 @@ ExprResult Sema::BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo,
     (void)DiagnoseUseOfDecl(Class, Loc);
   // Find the method we are messaging.
   if (!Method) {
-    if (Class->isForwardDecl()) {
-      if (getLangOptions().ObjCAutoRefCount) {
-        Diag(Loc, diag::err_arc_receiver_forward_class) << ReceiverType;
-      } else {
-        Diag(Loc, diag::warn_receiver_forward_class) << Class->getDeclName();
-      }
-
+    SourceRange TypeRange 
+      = SuperLoc.isValid()? SourceRange(SuperLoc)
+                          : ReceiverTypeInfo->getTypeLoc().getSourceRange();
+    if (RequireCompleteType(Loc, Context.getObjCInterfaceType(Class), 
+                            (getLangOptions().ObjCAutoRefCount
+                               ? PDiag(diag::err_arc_receiver_forward_class)
+                               : PDiag(diag::warn_receiver_forward_class))
+                                   << TypeRange)) {
       // A forward class used in messaging is treated as a 'Class'
       Method = LookupFactoryMethodInGlobalPool(Sel, 
                                                SourceRange(LBracLoc, RBracLoc));
@@ -1322,13 +1319,21 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
         // We allow sending a message to a pointer to an interface (an object).
         ClassDecl = OCIType->getInterfaceDecl();
 
-        if (ClassDecl->isForwardDecl() && getLangOptions().ObjCAutoRefCount) {
-          Diag(Loc, diag::err_arc_receiver_forward_instance)
-            << OCIType->getPointeeType()
-            << (Receiver ? Receiver->getSourceRange() : SourceRange(SuperLoc));
-          return ExprError();
+        // Try to complete the type. Under ARC, this is a hard error from which
+        // we don't try to recover.
+        const ObjCInterfaceDecl *forwardClass = 0;
+        if (RequireCompleteType(Loc, OCIType->getPointeeType(),
+              getLangOptions().ObjCAutoRefCount
+                ? PDiag(diag::err_arc_receiver_forward_instance)
+                    << (Receiver ? Receiver->getSourceRange() 
+                                 : SourceRange(SuperLoc))
+                : PDiag())) {
+          if (getLangOptions().ObjCAutoRefCount)
+            return ExprError();
+          
+          forwardClass = OCIType->getInterfaceDecl();
         }
-
+        
         // FIXME: consider using LookupInstanceMethodInGlobalPool, since it will be
         // faster than the following method (which can do *many* linear searches).
         // The idea is to add class info to MethodPool.
@@ -1338,7 +1343,6 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
           // Search protocol qualifiers.
           Method = LookupMethodInQualifiedType(Sel, OCIType, true);
         
-        const ObjCInterfaceDecl *forwardClass = 0;
         if (!Method) {
           // If we have implementations in scope, check "private" methods.
           Method = LookupPrivateInstanceMethod(Sel, ClassDecl);
@@ -1356,8 +1360,6 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
             if (OCIType->qual_empty()) {
               Method = LookupInstanceMethodInGlobalPool(Sel,
                                                  SourceRange(LBracLoc, RBracLoc));
-              if (OCIType->getInterfaceDecl()->isForwardDecl())
-                forwardClass = OCIType->getInterfaceDecl();
               if (Method && !forwardClass)
                 Diag(Loc, diag::warn_maynot_respond)
                   << OCIType->getInterfaceDecl()->getIdentifier() << Sel;
index a424a8a1b0e1bcbfd13989a30fa3022d03471790..e8a61044b5dd4966d93034d22a9f5e4ede49261f 100644 (file)
@@ -1060,13 +1060,13 @@ Sema::ActOnObjCForCollectionOperand(SourceLocation forLoc, Expr *collection) {
   ObjCInterfaceDecl *iface = objectType->getInterface();
 
   // If we have a forward-declared type, we can't do this check.
-  if (iface && iface->isForwardDecl()) {
-    // This is ill-formed under ARC.
-    if (getLangOptions().ObjCAutoRefCount) {
-      Diag(forLoc, diag::err_arc_collection_forward)
-        << pointerType->getPointeeType() << collection->getSourceRange();
-    }
-
+  // Under ARC, it is an error not to have a forward-declared class.
+  if (iface && 
+      RequireCompleteType(forLoc, QualType(objectType, 0),
+                          getLangOptions().ObjCAutoRefCount
+                            ? PDiag(diag::err_arc_collection_forward)
+                                << collection->getSourceRange()
+                          : PDiag(0))) {
     // Otherwise, if we have any useful type information, check that
     // the type declares the appropriate method.
   } else if (iface || !objectType->qual_empty()) {
index c0d910b42863c08500b15374fc40c61adbac9431..6ea3f4827a1b8825b219a00e20753118a53c3128 100644 (file)
@@ -4098,21 +4098,36 @@ bool Sema::RequireCompleteType(SourceLocation Loc, QualType T,
     return true;
 
   const TagType *Tag = T->getAs<TagType>();
+  const ObjCInterfaceType *IFace = 0;
+  
+  if (Tag) {
+    // Avoid diagnosing invalid decls as incomplete.
+    if (Tag->getDecl()->isInvalidDecl())
+      return true;
 
-  // Avoid diagnosing invalid decls as incomplete.
-  if (Tag && Tag->getDecl()->isInvalidDecl())
-    return true;
-
-  // Give the external AST source a chance to complete the type.
-  if (Tag && Tag->getDecl()->hasExternalLexicalStorage()) {
-    Context.getExternalSource()->CompleteType(Tag->getDecl());
-    if (!Tag->isIncompleteType())
-      return false;
+    // Give the external AST source a chance to complete the type.
+    if (Tag->getDecl()->hasExternalLexicalStorage()) {
+      Context.getExternalSource()->CompleteType(Tag->getDecl());
+      if (!Tag->isIncompleteType())
+        return false;
+    }
   }
-
+  else if ((IFace = T->getAs<ObjCInterfaceType>())) {
+    // Avoid diagnosing invalid decls as incomplete.
+    if (IFace->getDecl()->isInvalidDecl())
+      return true;
+    
+    // Give the external AST source a chance to complete the type.
+    if (IFace->getDecl()->hasExternalLexicalStorage()) {
+      Context.getExternalSource()->CompleteType(IFace->getDecl());
+      if (!IFace->isIncompleteType())
+        return false;
+    }
+  }
+    
   // We have an incomplete type. Produce a diagnostic.
   Diag(Loc, PD) << T;
-
+    
   // If we have a note, produce it.
   if (!Note.first.isInvalid())
     Diag(Note.first, Note.second);
@@ -4123,7 +4138,11 @@ bool Sema::RequireCompleteType(SourceLocation Loc, QualType T,
     Diag(Tag->getDecl()->getLocation(),
          Tag->isBeingDefined() ? diag::note_type_being_defined
                                : diag::note_forward_declaration)
-        << QualType(Tag, 0);
+      << QualType(Tag, 0);
+  
+  // If the Objective-C class was a forward declaration, produce a note.
+  if (IFace && !IFace->getDecl()->isInvalidDecl())
+    Diag(IFace->getDecl()->getLocation(), diag::note_forward_class);
 
   return true;
 }
index b2a113c20dcf44b4cea1d9c6ffab275490d2eefd..d710c475defe9184cef9de28555eea0546d1fc1c 100644 (file)
@@ -10,7 +10,7 @@ typedef struct _NSZone NSZone;
 @interface NSObject <NSObject> {} @end
 extern id NSAllocateObject(Class aClass, NSUInteger extraBytes, NSZone *zone);
 @class NSArray;
-@class NSMutableArray, NSIndexSet, NSView, NSPredicate, NSString, NSViewAnimation, NSTimer;
+@class NSMutableArray, NSIndexSet, NSView, NSPredicate, NSString, NSViewAnimation, NSTimer; // expected-note{{forward declaration of class here}}
 @interface FooBazController : NSObject {}
 @end
 typedef struct {} TazVersion;
index c0393c46cc40c815ddd5ba719822780955063c91..b3405c05e2627bfa5807b0fbfe9c1288571dca22 100644 (file)
@@ -378,7 +378,7 @@ void test16(void) {
   [v test16_6: 0];
 }
 
-@class Test17;
+@class Test17; // expected-note 2{{forward declaration of class here}}
 @protocol Test17p
 - (void) test17;
 + (void) test17;
@@ -651,7 +651,7 @@ void test36(int first, ...) {
   __builtin_va_end(arglist);
 }
 
-@class Test37;
+@class Test37; // expected-note{{forward declaration of class here}}
 void test37(Test37 *c) {
   for (id y in c) { // expected-error {{collection expression type 'Test37' is a forward declaration}}
     (void) y;
index 4cc5dafaa91b4c7d06b2a2ea8e18a063c90da72f..f2d4abd5aeb167c26d36935f4f38a2f1396527d6 100644 (file)
@@ -31,9 +31,9 @@
 
 @interface UnknownClass  (Category) @end // expected-error {{cannot find interface declaration for 'UnknownClass'}}
 
-@class MyClass2;
+@class MyClass2; // expected-note{{forward declaration of class here}}
 
-@interface MyClass2  (Category) @end  // expected-error {{cannot find interface declaration for 'MyClass2'}}
+@interface MyClass2  (Category) @end  // expected-error {{cannot define category for undefined class 'MyClass2'}}
 
 @interface XCRemoteComputerManager
 @end
index 90a4112c712241579b4412f91bde216165304d20..170ccb98facbb0470d7944b7d412b7d388f8233a 100644 (file)
@@ -31,7 +31,7 @@ typedef int INTF3; // expected-note {{previous definition is here}}
 
 @implementation INTF4 @end // expected-warning {{cannot find interface declaration for 'INTF4'}}
 
-@class INTF5;
+@class INTF5; // expected-note{{forward declaration of class here}}
 
 @implementation INTF5 {  // expected-warning {{cannot find interface declaration for 'INTF5'}}
   int x;
index 80309764335b77a4c8d8171a938f696f0df0a3e5..02c40aab65995e3c7807ca0424261ee63b3144f1 100644 (file)
@@ -23,7 +23,7 @@
 
 @interface E2 <p1,p2,p3> @end  // expected-warning {{cannot find protocol definition for 'p3'}}
 
-@class U1, U2; // expected-note {{forward class is declared here}}
+@class U1, U2; // expected-note {{forward declaration of class here}}
 
 @interface E3 : U1 @end // expected-error {{attempting to use the forward class 'U1' as superclass of 'E3'}}
 
index 2b505e0eae332c88a0e05709e79cdeb97e7b2f0e..b198cba4a9b1a2ca4de2663de6668a073dc93a24 100644 (file)
@@ -33,7 +33,7 @@ void test3(Object *o) {
   __sync_bool_compare_and_swap(&g, 0, o);
 }
 
-@class Incomplete_ObjC_class;
+@class Incomplete_ObjC_class; // expected-note{{forward declaration of class here}}
 struct Incomplete_struct; // expected-note {{forward declaration}}
 
 void test_encode() {
index de94e884aee2735de81ae637f5f7a0a1ddc07ee4..3a9a8ac82d9090763b7be4cfb90bfc6c73719d1a 100644 (file)
@@ -1,6 +1,6 @@
 // RUN: %clang_cc1 -fsyntax-only -verify %s
 
-@class FOO, BAR; // expected-note {{forward class is declared here}}
+@class FOO, BAR; // expected-note {{forward declaration of class here}}
 @class FOO, BAR;
 
 @interface INTF : FOO  // expected-error {{attempting to use the forward class 'FOO' as superclass of 'INTF'}}
@@ -46,7 +46,7 @@ typedef NSObject <XCElementP> XCElement;
 
 
 // rdar://9653341
-@class B; // expected-note {{forward class is declared here}}
+@class B; // expected-note {{forward declaration of class here}}
 @interface A : B {} // expected-error {{attempting to use the forward class 'B' as superclass of 'A'}}
 @end
 
index 55b29c15c5c31df5b558340cd5de1537e0cd978f..9bcb03961dc0ab185b36303633892c08de55ff01 100644 (file)
@@ -5,7 +5,7 @@
 @end
 Class isa;
 
-@class NotKnown;
+@class NotKnown; // expected-note{{forward declaration of class here}}
 
 void foo(NotKnown *n) {
   [isa new];
index 2b6564d2959399b187bf0221a9c45c85eafdc79e..4ef21cc145c03f19a6d6f10890093fcf830bf67d 100644 (file)
@@ -97,13 +97,13 @@ typedef signed char BOOL;
 @end
 
 // rdar://8774513
-@class MDAInstance; // expected-note {{forward class is declared here}}
+@class MDAInstance; // expected-note {{forward declaration of class here}}
 
 @interface MDATestDocument
 @property(retain) MDAInstance *instance;
 @end
 
 id f0(MDATestDocument *d) {
-  return d.instance.path; // expected-error {{property 'path' cannot be found in forward class object 'MDAInstance *'}}
+  return d.instance.path; // expected-error {{property 'path' cannot be found in forward class object 'MDAInstance'}}
 }
 
index bf75601b79bcb8420283358579cd627a4beab258..3ebf0a81159c5bcaa72ea8e2e1ff8928ccd06288 100644 (file)
@@ -21,7 +21,7 @@ void f3(id o)
 }
 
 // rdar://8851803
-@class SomeOtherClass; // expected-note {{forward class is declared here}}
+@class SomeOtherClass; // expected-note {{forward declaration of class here}}
 
 @interface MyClass {
     SomeOtherClass *someOtherObject;
index 43870a17a30fa7cabb3a60b783d78f55151bd439..dd8c1fdca00dc218ef6dd70edc31de53c29294d6 100644 (file)
@@ -1,6 +1,6 @@
 // RUN: %clang_cc1 -verify -fsyntax-only %s
 
-@class I0;
+@class I0; // expected-note 3{{forward declaration of class here}}
 
 // rdar://6811884
 int g0 = sizeof(I0); // expected-error{{invalid application of 'sizeof' to an incomplete type 'I0'}}
index fb0f6604e6bf0673e6c09596e889f322430dea2a..916411144183942424f86d3cd5d218adf0fe07f0 100644 (file)
@@ -27,7 +27,7 @@
 @end
 
 
-@class C;      // expected-note 5 {{forward class is declared here}}
+@class C;      // expected-note 5 {{forward declaration of class here}}
 
 void test(C *c) {
   [c depInA]; // expected-warning {{'depInA' maybe deprecated because receiver type is unknown}}
index 41cf1439bd9c7d34f01525984f6ce17b7489cc67..ef2f1929716f35607987787b7cc948173cf4e3fe 100644 (file)
@@ -1,6 +1,6 @@
 // RUN: %clang_cc1 -fsyntax-only -verify %s
 
-@class SUPER, Y; // expected-note 2 {{forward class is declared here}}
+@class SUPER, Y; // expected-note 2 {{forward declaration of class here}}
 
 @interface INTF :SUPER  // expected-error {{attempting to use the forward class 'SUPER' as superclass of 'INTF'}}
 @end