From: Fariborz Jahanian Date: Fri, 18 Apr 2008 00:19:30 +0000 (+0000) Subject: Initial work for property implementation declarations. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f624f8186d8fe474350051c6d3f00b2c204fbeae;p=clang Initial work for property implementation declarations. Mostly semantic checking in this patch. This is on going and incomplete. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@49882 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h index 55115055ae..e0c9563911 100644 --- a/include/clang/AST/DeclObjC.h +++ b/include/clang/AST/DeclObjC.h @@ -27,6 +27,7 @@ class ObjCMethodDecl; class ObjCProtocolDecl; class ObjCCategoryDecl; class ObjCPropertyDecl; +class ObjCPropertyImplDecl; /// ObjCMethodDecl - Represents an instance or class method declaration. /// ObjC methods can be declared within 4 contexts: class interfaces, @@ -807,6 +808,9 @@ class ObjCCategoryImplDecl : public NamedDecl { /// implemented class methods llvm::SmallVector ClassMethods; + + /// Propertys' being implemented + llvm::SmallVector PropertyImplementations; SourceLocation EndLoc; @@ -829,13 +833,20 @@ public: } void addClassMethod(ObjCMethodDecl *method) { ClassMethods.push_back(method); - } + } // Get the instance method definition for this implementation. ObjCMethodDecl *getInstanceMethod(Selector Sel); // Get the class method definition for this implementation. ObjCMethodDecl *getClassMethod(Selector Sel); + + void addPropertyImplementation(ObjCPropertyImplDecl *property) { + PropertyImplementations.push_back(property); + } + unsigned getNumPropertyImplementations() const + { return PropertyImplementations.size(); } + typedef llvm::SmallVector::const_iterator instmeth_iterator; instmeth_iterator instmeth_begin() const { return InstanceMethods.begin(); } @@ -888,6 +899,9 @@ class ObjCImplementationDecl : public NamedDecl { /// implemented class methods llvm::SmallVector ClassMethods; + /// Propertys' being implemented + llvm::SmallVector PropertyImplementations; + SourceLocation EndLoc; ObjCImplementationDecl(SourceLocation L, IdentifierInfo *Id, @@ -912,6 +926,11 @@ public: void addClassMethod(ObjCMethodDecl *method) { ClassMethods.push_back(method); } + + void addPropertyImplementation(ObjCPropertyImplDecl *property) { + PropertyImplementations.push_back(property); + } + // Location information, modeled after the Stmt API. SourceLocation getLocStart() const { return getLocation(); } SourceLocation getLocEnd() const { return EndLoc; } @@ -926,6 +945,9 @@ public: unsigned getNumInstanceMethods() const { return InstanceMethods.size(); } unsigned getNumClassMethods() const { return ClassMethods.size(); } + + unsigned getNumPropertyImplementations() const + { return PropertyImplementations.size(); } typedef llvm::SmallVector::const_iterator instmeth_iterator; @@ -1041,14 +1063,15 @@ public: OBJC_PR_IMPL_DYNAMIC }; private: + SourceLocation AtLoc; // location of @syntheisze or @dynamic /// Property declaration being implemented ObjCPropertyDecl *PropertyDecl; PropertyImplKind PropertyImplementation; /// Null for @dynamic. Required for @synthesize. ObjCIvarDecl *PropertyIvarDecl; public: - ObjCPropertyImplDecl(SourceLocation L) - : Decl(ObjCPropertyImpl, L), PropertyDecl(0), + ObjCPropertyImplDecl(SourceLocation atLoc, SourceLocation L) + : Decl(ObjCPropertyImpl, L), AtLoc(atLoc), PropertyDecl(0), PropertyImplementation(OBJC_PR_IMPL_None), PropertyIvarDecl(0) {} void setPropertyDecl(ObjCPropertyDecl *property) { PropertyDecl = property; } diff --git a/include/clang/Basic/DiagnosticKinds.def b/include/clang/Basic/DiagnosticKinds.def index 8e2f69b222..f8dc4d1629 100644 --- a/include/clang/Basic/DiagnosticKinds.def +++ b/include/clang/Basic/DiagnosticKinds.def @@ -487,6 +487,20 @@ DIAG(error_bad_receiver_type, ERROR, "bad receiver type '%0'") DIAG(error_no_super_class, ERROR, "no super class declared in @interface for '%0'") +DIAG(error_missing_property_context, ERROR, + "missing context for property implementation declaration") +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'") +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") +DIAG(error_missing_property_ivar_decl, ERROR, + "property synthesize requires a previously declared ivar") //===----------------------------------------------------------------------===// // Semantic Analysis diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h index 217d8b1947..2c55d25e5f 100644 --- a/include/clang/Parse/Action.h +++ b/include/clang/Parse/Action.h @@ -626,6 +626,18 @@ public: SourceLocation CatLoc) { return 0; } + // ActOnPropertyImplDecl - called for every property implementation + virtual DeclTy *ActOnPropertyImplDecl( + SourceLocation AtLoc, // location of the @syntheize/@dynamic + SourceLocation PropertyNameLoc, // location for the property name + bool ImplKind, // true for @synthesize, false for + // @dynamic + DeclTy *ClassImplDecl, // class or category implementation + IdentifierInfo *propertyId, // name of property + IdentifierInfo *propertyIvar) { // name of the ivar + return 0; + } + // ActOnMethodDeclaration - called for all method declarations. virtual DeclTy *ActOnMethodDeclaration( SourceLocation BeginLoc, // location of the + or -. diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp index ec40e36479..ede0edb354 100644 --- a/lib/Parse/ParseObjc.cpp +++ b/lib/Parse/ParseObjc.cpp @@ -1031,13 +1031,15 @@ Parser::DeclTy *Parser::ParseObjCAtAliasDeclaration(SourceLocation atLoc) { Parser::DeclTy *Parser::ParseObjCPropertySynthesize(SourceLocation atLoc) { assert(Tok.isObjCAtKeyword(tok::objc_synthesize) && "ParseObjCPropertyDynamic(): Expected '@synthesize'"); - SourceLocation loc = ConsumeToken(); // consume dynamic + SourceLocation loc = ConsumeToken(); // consume synthesize if (Tok.isNot(tok::identifier)) { Diag(Tok, diag::err_expected_ident); return 0; } while (Tok.is(tok::identifier)) { - ConsumeToken(); // consume property name + IdentifierInfo *propertyIvar = 0; + IdentifierInfo *propertyId = Tok.getIdentifierInfo(); + SourceLocation propertyLoc = ConsumeToken(); // consume property name if (Tok.is(tok::equal)) { // property '=' ivar-name ConsumeToken(); // consume '=' @@ -1045,8 +1047,11 @@ Parser::DeclTy *Parser::ParseObjCPropertySynthesize(SourceLocation atLoc) { Diag(Tok, diag::err_expected_ident); break; } + propertyIvar = Tok.getIdentifierInfo(); ConsumeToken(); // consume ivar-name } + Actions.ActOnPropertyImplDecl(atLoc, propertyLoc, true, ObjCImpDecl, + propertyId, propertyIvar); if (Tok.isNot(tok::comma)) break; ConsumeToken(); // consume ',' diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 50842f7d3a..9d60093ca9 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -656,7 +656,13 @@ public: DeclTy **allProperties = 0, unsigned pNum = 0); virtual DeclTy *ActOnProperty(Scope *S, SourceLocation AtLoc, - FieldDeclarator &FD, ObjCDeclSpec &ODS); + FieldDeclarator &FD, ObjCDeclSpec &ODS); + virtual DeclTy *ActOnPropertyImplDecl(SourceLocation AtLoc, + SourceLocation PropertyLoc, + bool ImplKind, DeclTy *ClassImplDecl, + IdentifierInfo *PropertyId, + IdentifierInfo *PropertyIvar); + virtual DeclTy *ActOnMethodDeclaration( SourceLocation BeginLoc, // location of the + or -. SourceLocation EndLoc, // location of the ; or {. diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index eb9fa433d9..b0ae1f28ea 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -929,5 +929,116 @@ Sema::DeclTy *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc, return PDecl; } - +/// ActOnPropertyImplDecl - This routine performas semantic checks and +/// build the AST node for a property implementation declaration; declared +/// as @synthesize ot @dynamic +/// +Sema::DeclTy *Sema::ActOnPropertyImplDecl(SourceLocation AtLoc, + SourceLocation PropertyLoc, + bool Synthesize, + DeclTy *ClassCatImpDecl, + IdentifierInfo *PropertyId, + IdentifierInfo *PropertyIvar) { + Decl *ClassImpDecl = static_cast(ClassCatImpDecl); + // Make sure we have a context for the property implementation declaration. + if (!ClassImpDecl) { + Diag(AtLoc, diag::error_missing_property_context); + return 0; + } + ObjCPropertyDecl *property = 0; + ObjCInterfaceDecl* IDecl = 0; + // Find the class or category class where this property must have + // a declaration. + if (ObjCImplementationDecl *IC = + dyn_cast(ClassImpDecl)) { + IDecl = getObjCInterfaceDecl(IC->getIdentifier()); + if (!IDecl) { + Diag(AtLoc, diag::error_missing_property_interface); + return 0; + } + // Look for this property declaration in the @implementation's @interface + ObjCInterfaceDecl::classprop_iterator I,E; + for (I = IDecl->classprop_begin(), + E = IDecl->classprop_end(); I != E; ++I) { + property = *I; + if (property->getIdentifier() == PropertyId) + break; + } + if (I == E) { + Diag(PropertyLoc, diag::error_bad_property_decl, IDecl->getName()); + return 0; + } + } + else if (ObjCCategoryImplDecl* CatImplClass = + dyn_cast(ClassImpDecl)) { + IDecl = CatImplClass->getClassInterface(); + if (!IDecl) { + Diag(AtLoc, diag::error_missing_property_interface); + return 0; + } + ObjCCategoryDecl *Categories; + for (ObjCCategoryDecl *Categories = IDecl->getCategoryList(); + Categories; Categories = Categories->getNextClassCategory()) + if (Categories->getIdentifier() == CatImplClass->getIdentifier()) + break; + // If category for this implementation not found, it is an error which + // has already been reported eralier. + if (!Categories) + return 0; + // Look for this property declaration in @implementation's category + ObjCCategoryDecl::classprop_iterator I,E; + for (I = Categories->classprop_begin(), + E = Categories->classprop_end(); I != E; ++I) { + property = *I; + if (property->getIdentifier() == PropertyId) + break; + } + if (I == E) { + Diag(PropertyLoc, diag::error_bad_property_decl, + Categories->getName()); + return 0; + } + } + else { + Diag(AtLoc, diag::error_bad_property_context); + return 0; + } + + // Check that we have a valid, previously declared ivar for @synthesize + if (Synthesize) { + // @synthesize + if (!PropertyIvar) { + Diag(PropertyLoc, diag::error_property_ivar_decl); + return 0; + } + // Check that this is a previously declared 'ivar' in 'IDecl' interface + ObjCInterfaceDecl::ivar_iterator IVI, IVE; + for (IVI = IDecl->ivar_begin(), IVE = IDecl->ivar_end(); + IVI != IVE; ++IVI) { + ObjCIvarDecl* ImplIvar = (*IVI); + if (ImplIvar->getIdentifier() == PropertyIvar) + break; + } + if (IVI == IVE) { + Diag(PropertyLoc, diag::error_missing_property_ivar_decl); + 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 +#if 0 + ObjCCategoryImplDecl *PIDecl = + ObjCCategoryImplDecl::Create(AtLoc, PropertyLoc, property, + Synthesize ? ObjCPropertyImplDecl::OBJC_PR_IMPL_SYNTHSIZE + : ObjCPropertyImplDecl::OBJC_PR_IMPL_DYNAMIC, + PropertyId, PropertyIvar); +#endif + return 0; +}