Support for @dynamic AST build.
More property semantics checking.
First test case for ObjC2's property implementation.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@50057 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h
index 6a34696..72c8e02 100644
--- a/include/clang/AST/DeclObjC.h
+++ b/include/clang/AST/DeclObjC.h
@@ -1066,6 +1066,8 @@
   static ObjCPropertyDecl *Create(ASTContext &C, SourceLocation L, 
                                   IdentifierInfo *Id, QualType T);
   QualType getType() const { return DeclType; }
+  QualType getCanonicalType() const { return DeclType.getCanonicalType(); }
+  
   PropertyAttributeKind getPropertyAttributes() const {
     return PropertyAttributeKind(PropertyAttributes);
   }
diff --git a/include/clang/Basic/DiagnosticKinds.def b/include/clang/Basic/DiagnosticKinds.def
index 4591210..4f46eaa 100644
--- a/include/clang/Basic/DiagnosticKinds.def
+++ b/include/clang/Basic/DiagnosticKinds.def
@@ -492,15 +492,21 @@
 DIAG(error_bad_property_context, ERROR,
      "property implementation must be in a class or category implementation")
 DIAG(error_bad_property_decl, ERROR,
-     "property implementation must have the declaration in the class '%0'")
+     "property implementation must have its declaration in the class '%0'")
+DIAG(error_bad_category_property_decl, ERROR,
+     "property implementation must have its declaration in the category '%0'")
 DIAG(error_property_ivar_decl, ERROR,
      "property synthesize requires specification of an ivar")
 DIAG(error_dynamic_property_ivar_decl, ERROR,
      "dynamic property can not have ivar specification")
 DIAG(error_missing_property_interface, ERROR,
-     "property implementation in a class/category implementation with no interface")
+     "property implementation in a category with no category declaration")
 DIAG(error_missing_property_ivar_decl, ERROR,
      "property synthesize requires a previously declared ivar")
+DIAG(error_synthesize_category_decl, ERROR,
+     "@synthesize not allowed in a category's implementation")
+DIAG(error_property_ivar_type, ERROR,
+     "type of property '%0'  does not match type of ivar '%1'") 
 
 //===----------------------------------------------------------------------===//
 // Semantic Analysis
diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp
index ede0edb..0c5cf20 100644
--- a/lib/Parse/ParseObjc.cpp
+++ b/lib/Parse/ParseObjc.cpp
@@ -1077,7 +1077,11 @@
     return 0;
   }
   while (Tok.is(tok::identifier)) {
-    ConsumeToken(); // consume property name
+    IdentifierInfo *propertyId = Tok.getIdentifierInfo();
+    SourceLocation propertyLoc = ConsumeToken(); // consume property name
+    Actions.ActOnPropertyImplDecl(atLoc, propertyLoc, false, ObjCImpDecl,
+                                  propertyId, 0);
+
     if (Tok.isNot(tok::comma))
       break;
     ConsumeToken(); // consume ','
diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp
index 21130a04..45d8777 100644
--- a/lib/Sema/SemaDeclObjC.cpp
+++ b/lib/Sema/SemaDeclObjC.cpp
@@ -952,10 +952,11 @@
   if (ObjCImplementationDecl *IC = 
         dyn_cast<ObjCImplementationDecl>(ClassImpDecl)) {
     IDecl = getObjCInterfaceDecl(IC->getIdentifier());
-    if (!IDecl) {
-      Diag(AtLoc, diag::error_missing_property_interface);
-      return 0;
-    }
+    // We always synthesize an interface for an implementation
+    // without an interface decl. So, IDecl is always non-zero.
+    assert(IDecl && 
+           "ActOnPropertyImplDecl - @implementation without @interface");
+    
     // Look for this property declaration in the @implementation's @interface
     property = IDecl->FindPropertyDeclaration(PropertyId);
     if (!property) {
@@ -965,6 +966,10 @@
   }
   else if (ObjCCategoryImplDecl* CatImplClass = 
             dyn_cast<ObjCCategoryImplDecl>(ClassImpDecl)) {
+    if (Synthesize) {
+      Diag(AtLoc, diag::error_synthesize_category_decl);
+      return 0;
+    }    
     IDecl = CatImplClass->getClassInterface();
     if (!IDecl) {
       Diag(AtLoc, diag::error_missing_property_interface);
@@ -980,7 +985,7 @@
     // Look for this property declaration in @implementation's category
     property = Category->FindPropertyDeclaration(PropertyId);
     if (!property) {
-      Diag(PropertyLoc, diag::error_bad_property_decl, 
+      Diag(PropertyLoc, diag::error_bad_category_property_decl, 
            Category->getName());
       return 0;
     }
@@ -998,16 +1003,23 @@
       return 0;
     }
     // Check that this is a previously declared 'ivar' in 'IDecl' interface
-    if (!IDecl->FindIvarDeclaration(PropertyIvar)) {
+    ObjCIvarDecl *Ivar = IDecl->FindIvarDeclaration(PropertyIvar);
+    if (!Ivar) {
       Diag(PropertyLoc, diag::error_missing_property_ivar_decl);
       return 0;
     }
+    // Check that type of property and its ivar match. 
+    if (Ivar->getCanonicalType() != property->getCanonicalType()) {
+      Diag(PropertyLoc, diag::error_property_ivar_type, property->getName(),
+           Ivar->getName());
+      return 0;
+    }
+      
   } else if (PropertyIvar) {
     // @dynamic
     Diag(PropertyLoc, diag::error_dynamic_property_ivar_decl);
     return 0;
   }
-  // TODO: More diagnostics go here !!
   assert (property && "ActOnPropertyImplDecl - property declaration missing");
   // TODO: Build the property implementation AST, pushes it into its 
   // class/cateogory implementation's vector of property implementations
diff --git a/test/Sema/objc-property-1.m b/test/Sema/objc-property-1.m
new file mode 100644
index 0000000..d307d13
--- /dev/null
+++ b/test/Sema/objc-property-1.m
@@ -0,0 +1,36 @@
+// RUN: clang -fsyntax-only -verify %s
+
+@interface I 
+{
+	int IVAR;
+}
+@property int d1;
+@property id  prop_id;
+@end
+
+@interface I(CAT)
+@property int d1;
+@end
+
+@implementation I
+@synthesize d1;		// expected-error {{property synthesize requires specification of an ivar}}
+@dynamic    bad;	// expected-error {{property implementation must have its declaration in the class 'I'}}
+@synthesize prop_id;	// expected-error {{property synthesize requires specification of an ivar}}
+@synthesize prop_id = IVAR;	// expected-error {{type of property 'prop_id'  does not match type of ivar 'IVAR'}}
+@end
+
+@implementation I(CAT)
+@synthesize d1;		// expected-error {{@synthesize not allowed in a category's implementation}}
+@dynamic bad;		// expected-error {{property implementation must have its declaration in the category 'CAT'}}
+@end
+
+@implementation E	// expected-warning {{cannot find interface declaration for 'E'}}
+@dynamic d;		// expected-error {{property implementation must have its declaration in the class 'E'}}
+@end
+
+@implementation Q(MYCAT)  // expected-error {{cannot find interface declaration for 'Q'}}
+@dynamic d;		// expected-error {{property implementation in a category with no category declaration}}
+@end
+
+
+