diff options
-rw-r--r-- | AST/Decl.cpp | 24 | ||||
-rw-r--r-- | Driver/RewriteTest.cpp | 4 | ||||
-rw-r--r-- | Parse/ParseObjc.cpp | 19 | ||||
-rw-r--r-- | Parse/Parser.cpp | 1 | ||||
-rw-r--r-- | Sema/Sema.h | 7 | ||||
-rw-r--r-- | Sema/SemaDecl.cpp | 42 | ||||
-rw-r--r-- | include/clang/AST/DeclObjC.h | 49 | ||||
-rw-r--r-- | include/clang/Parse/Action.h | 22 | ||||
-rw-r--r-- | include/clang/Parse/Parser.h | 3 | ||||
-rw-r--r-- | test/Sema/message.m | 2 |
10 files changed, 83 insertions, 90 deletions
diff --git a/AST/Decl.cpp b/AST/Decl.cpp index 2e79de3f63..584fbf5a63 100644 --- a/AST/Decl.cpp +++ b/AST/Decl.cpp @@ -408,26 +408,6 @@ void ObjcCategoryImplDecl::addMethods(ObjcMethodDecl **insMethods, } } -/// ObjcAddImplMethods - Insert instance and methods declarations into -/// ObjcImplementationDecl's InsMethods and ClsMethods fields. -/// -void ObjcImplementationDecl::addMethods(ObjcMethodDecl **insMethods, - unsigned numInsMembers, - ObjcMethodDecl **clsMethods, - unsigned numClsMembers, - SourceLocation AtEndLoc) { - NumInstanceMethods = numInsMembers; - if (numInsMembers) { - InstanceMethods = new ObjcMethodDecl*[numInsMembers]; - memcpy(InstanceMethods, insMethods, numInsMembers*sizeof(ObjcMethodDecl*)); - } - NumClassMethods = numClsMembers; - if (numClsMembers) { - ClassMethods = new ObjcMethodDecl*[numClsMembers]; - memcpy(ClassMethods, clsMethods, numClsMembers*sizeof(ObjcMethodDecl*)); - } -} - // lookupInstanceMethod - This method returns an instance method by looking in // the class, it's categories, and it's super classes (using a linear search). ObjcMethodDecl *ObjcInterfaceDecl::lookupInstanceMethod(Selector &Sel) { @@ -514,7 +494,7 @@ ObjcMethodDecl *ObjcInterfaceDecl::lookupClassMethod(Selector &Sel) { // the class implementation. Unlike interfaces, we don't look outside the // implementation. ObjcMethodDecl *ObjcImplementationDecl::lookupInstanceMethod(Selector &Sel) { - ObjcMethodDecl **methods = getInstanceMethods(); + ObjcMethodDecl *const*methods = getInstanceMethods(); int methodCount = getNumInstanceMethods(); for (int i = 0; i < methodCount; ++i) { if (methods[i]->getSelector() == Sel) { @@ -528,7 +508,7 @@ ObjcMethodDecl *ObjcImplementationDecl::lookupInstanceMethod(Selector &Sel) { // the class implementation. Unlike interfaces, we don't look outside the // implementation. ObjcMethodDecl *ObjcImplementationDecl::lookupClassMethod(Selector &Sel) { - ObjcMethodDecl **methods = getClassMethods(); + ObjcMethodDecl *const*methods = getClassMethods(); int methodCount = getNumClassMethods(); for (int i = 0; i < methodCount; ++i) { if (methods[i]->getSelector() == Sel) { diff --git a/Driver/RewriteTest.cpp b/Driver/RewriteTest.cpp index b74faf5b69..a0a11470dc 100644 --- a/Driver/RewriteTest.cpp +++ b/Driver/RewriteTest.cpp @@ -118,7 +118,7 @@ namespace { void RewriteObjcCategoryImplDecl(ObjcCategoryImplDecl *CDecl, std::string &Result); - void RewriteObjcMethodsMetaData(ObjcMethodDecl **Methods, + void RewriteObjcMethodsMetaData(ObjcMethodDecl *const*Methods, int NumMethods, bool IsInstanceMethod, const char *prefix, @@ -1039,7 +1039,7 @@ void RewriteTest::SynthesizeObjcInternalStruct(ObjcInterfaceDecl *CDecl, // RewriteObjcMethodsMetaData - Rewrite methods metadata for instance or /// class methods. -void RewriteTest::RewriteObjcMethodsMetaData(ObjcMethodDecl **Methods, +void RewriteTest::RewriteObjcMethodsMetaData(ObjcMethodDecl *const*Methods, int NumMethods, bool IsInstanceMethod, const char *prefix, diff --git a/Parse/ParseObjc.cpp b/Parse/ParseObjc.cpp index 4fbbc1854f..7bf1483682 100644 --- a/Parse/ParseObjc.cpp +++ b/Parse/ParseObjc.cpp @@ -275,12 +275,8 @@ void Parser::ParseObjCInterfaceDeclList(DeclTy *interfaceDecl, } } /// Insert collected methods declarations into the @interface object. - /// This action is executed even if we don't have any methods (so the @end - /// can be recorded properly). - Actions.ActOnAddMethodsToObjcDecl(CurScope, interfaceDecl, &allMethods[0], - allMethods.size(), - &allProperties[0], allProperties.size(), - AtEndLoc); + Actions.ActOnAtEnd(AtEndLoc, interfaceDecl, &allMethods[0], allMethods.size(), + &allProperties[0], allProperties.size()); } /// Parse property attribute declarations. @@ -946,12 +942,7 @@ Parser::DeclTy *Parser::ParseObjCAtEndDeclaration(SourceLocation atLoc) { // Checking is not necessary except that a parse error might have caused // @implementation not to have been parsed to completion and ObjcImpDecl // could be 0. - /// Insert collected methods declarations into the @interface object. - Actions.ActOnAddMethodsToObjcDecl(CurScope, ObjcImpDecl, - &AllImplMethods[0], AllImplMethods.size(), - (DeclTy **)0, 0, - atLoc); - AllImplMethods.clear(); + Actions.ActOnAtEnd(atLoc, ObjcImpDecl); } return ObjcImpDecl; @@ -1151,8 +1142,6 @@ Parser::StmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) { void Parser::ParseObjCInstanceMethodDefinition() { assert(Tok.is(tok::minus) && "Method definitions should start with '-'"); DeclTy *MDecl = ParseObjCMethodPrototype(ObjcImpDecl); - // FIXME: @optional/@protocol?? - AllImplMethods.push_back(MDecl); // parse optional ';' if (Tok.is(tok::semi)) ConsumeToken(); @@ -1169,8 +1158,6 @@ void Parser::ParseObjCInstanceMethodDefinition() { void Parser::ParseObjCClassMethodDefinition() { assert(Tok.is(tok::plus) && "Class method definitions should start with '+'"); DeclTy *MDecl = ParseObjCMethodPrototype(ObjcImpDecl); - // FIXME: @optional/@protocol?? - AllImplMethods.push_back(MDecl); // parse optional ';' if (Tok.is(tok::semi)) ConsumeToken(); diff --git a/Parse/Parser.cpp b/Parse/Parser.cpp index 1f8e016bfe..bfe342d26a 100644 --- a/Parse/Parser.cpp +++ b/Parse/Parser.cpp @@ -23,7 +23,6 @@ Parser::Parser(Preprocessor &pp, Action &actions) NumCachedScopes = 0; ParenCount = BracketCount = BraceCount = 0; ObjcImpDecl = 0; - AllImplMethods.clear(); } /// Out-of-line virtual destructor to provide home for Action class. diff --git a/Sema/Sema.h b/Sema/Sema.h index de464c111a..190302df99 100644 --- a/Sema/Sema.h +++ b/Sema/Sema.h @@ -541,10 +541,9 @@ public: llvm::SmallVector<DeclTy *, 8> & Protocols); - virtual void ActOnAddMethodsToObjcDecl(Scope* S, DeclTy *ClassDecl, - DeclTy **allMethods, unsigned allNum, - DeclTy **allProperties, unsigned pNum, - SourceLocation AtEndLoc); + virtual void ActOnAtEnd(SourceLocation AtEndLoc, DeclTy *classDecl, + DeclTy **allMethods = 0, unsigned allNum = 0, + DeclTy **allProperties = 0, unsigned pNum = 0); virtual DeclTy *ActOnAddObjcProperties(SourceLocation AtLoc, DeclTy **allProperties, diff --git a/Sema/SemaDecl.cpp b/Sema/SemaDecl.cpp index e9c438ffc5..e043fa19f6 100644 --- a/Sema/SemaDecl.cpp +++ b/Sema/SemaDecl.cpp @@ -1576,7 +1576,7 @@ void Sema::ImplMethodsVsClassMethods(ObjcImplementationDecl* IMPDecl, llvm::DenseSet<Selector> InsMap; // Check and see if instance methods in class interface have been // implemented in the implementation class. - ObjcMethodDecl **methods = IMPDecl->getInstanceMethods(); + ObjcMethodDecl *const*methods = IMPDecl->getInstanceMethods(); for (int i=0; i < IMPDecl->getNumInstanceMethods(); i++) InsMap.insert(methods[i]->getSelector()); @@ -2079,10 +2079,9 @@ void Sema::AddFactoryMethodToGlobalPool(ObjcMethodDecl *Method) { } } -void Sema::ActOnAddMethodsToObjcDecl(Scope* S, DeclTy *classDecl, - DeclTy **allMethods, unsigned allNum, - DeclTy **allProperties, unsigned pNum, - SourceLocation AtEndLoc) { +void Sema::ActOnAtEnd(SourceLocation AtEndLoc, DeclTy *classDecl, + DeclTy **allMethods, unsigned allNum, + DeclTy **allProperties, unsigned pNum) { Decl *ClassDecl = static_cast<Decl *>(classDecl); // FIXME: If we don't have a ClassDecl, we have an error. I (snaroff) would @@ -2164,8 +2163,7 @@ void Sema::ActOnAddMethodsToObjcDecl(Scope* S, DeclTy *classDecl, } else if (ObjcImplementationDecl *IC = dyn_cast<ObjcImplementationDecl>(ClassDecl)) { - IC->addMethods(&insMethods[0], insMethods.size(), - &clsMethods[0], clsMethods.size(), AtEndLoc); + IC->setLocEnd(AtEndLoc); if (ObjcInterfaceDecl* IDecl = getObjCInterfaceDecl(IC->getIdentifier())) ImplMethodsVsClassMethods(IC, IDecl); } else { @@ -2242,14 +2240,15 @@ Sema::DeclTy *Sema::ActOnMethodDeclaration( Decl *CDecl = static_cast<Decl*>(ClassDecl); ObjcInterfaceDecl *IDecl = 0; + ObjcImplementationDecl *ImpDecl = 0; if (isa<ObjcInterfaceDecl>(CDecl)) IDecl = cast<ObjcInterfaceDecl>(CDecl); else if (isa<ObjcCategoryDecl>(CDecl)) - IDecl = cast<ObjcCategoryDecl>(CDecl)->getClassInterface(); - else if (isa<ObjcImplementationDecl>(CDecl)) - IDecl = cast<ObjcImplementationDecl>(CDecl)->getClassInterface(); + IDecl = cast<ObjcCategoryDecl>(CDecl)->getClassInterface(); // FIXME: what is this? (talk to fariborz) + else if ((ImpDecl = dyn_cast<ObjcImplementationDecl>(CDecl))) + IDecl = ImpDecl->getClassInterface(); // FIXME: what is this? (talk to fariborz) else if (isa<ObjcCategoryImplDecl>(CDecl)) - IDecl = cast<ObjcCategoryImplDecl>(CDecl)->getClassInterface(); + IDecl = cast<ObjcCategoryImplDecl>(CDecl)->getClassInterface(); // FIXME: what is this? (talk to fariborz) ObjcMethodDecl* ObjcMethod = new ObjcMethodDecl(MethodLoc, EndLoc, Sel, resultDeclType, @@ -2262,6 +2261,27 @@ Sema::DeclTy *Sema::ActOnMethodDeclaration( ObjcMethod->setMethodParams(&Params[0], Sel.getNumArgs()); ObjcMethod->setObjcDeclQualifier( CvtQTToAstBitMask(ReturnQT.getObjcDeclQualifier())); + if (ImpDecl) { + // For implementations (which can be very "coarse grain"), we add the + // method now. This allows the AST to implement lookup methods that work + // incrementally (without waiting until we parse the @end). It also allows + // us to flag multiple declaration errors as they occur. + // FIXME: still need to do this for ObjcCategoryImplDecl. + const ObjcMethodDecl *PrevMethod = 0; + if (MethodType == tok::minus) { + PrevMethod = ImpDecl->lookupInstanceMethod(Sel); + ImpDecl->addInstanceMethod(ObjcMethod); + } else { + PrevMethod = ImpDecl->lookupClassMethod(Sel); + ImpDecl->addClassMethod(ObjcMethod); + } + if (PrevMethod) { + // You can never have two method definitions with the same name. + Diag(ObjcMethod->getLocation(), diag::error_duplicate_method_decl, + ObjcMethod->getSelector().getName()); + Diag(PrevMethod->getLocation(), diag::err_previous_declaration); + } + } return ObjcMethod; } diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h index 3fb09036e1..48cdce363e 100644 --- a/include/clang/AST/DeclObjC.h +++ b/include/clang/AST/DeclObjC.h @@ -629,44 +629,53 @@ class ObjcImplementationDecl : public NamedDecl { /// Optional Ivars/NumIvars - This is a new[]'d array of pointers to Decls. ObjcIvarDecl **Ivars; // Null if not specified int NumIvars; // -1 if not defined. - + /// implemented instance methods - ObjcMethodDecl **InstanceMethods; // Null if not defined - int NumInstanceMethods; // -1 if not defined - + llvm::SmallVector<ObjcMethodDecl*, 32> InstanceMethods; + /// implemented class methods - ObjcMethodDecl **ClassMethods; // Null if not defined - int NumClassMethods; // -1 if not defined - + llvm::SmallVector<ObjcMethodDecl*, 32> ClassMethods; + + SourceLocation EndLoc; public: ObjcImplementationDecl(SourceLocation L, IdentifierInfo *Id, ObjcInterfaceDecl *classInterface, ObjcInterfaceDecl *superDecl) : NamedDecl(ObjcImplementation, L, Id), - ClassInterface(classInterface), - SuperClass(superDecl), - Ivars(0), NumIvars(-1), - InstanceMethods(0), NumInstanceMethods(-1), - ClassMethods(0), NumClassMethods(-1) {} + ClassInterface(classInterface), SuperClass(superDecl), + Ivars(0), NumIvars(-1) {} void ObjcAddInstanceVariablesToClassImpl(ObjcIvarDecl **ivars, unsigned numIvars); - void addMethods(ObjcMethodDecl **insMethods, unsigned numInsMembers, - ObjcMethodDecl **clsMethods, unsigned numClsMembers, - SourceLocation AtEndLoc); - + void addInstanceMethod(ObjcMethodDecl *method) { + InstanceMethods.push_back(method); + } + void addClassMethod(ObjcMethodDecl *method) { + ClassMethods.push_back(method); + } + // Location information, modeled after the Stmt API. + SourceLocation getLocStart() const { return getLocation(); } + SourceLocation getLocEnd() const { return EndLoc; } + void setLocEnd(SourceLocation LE) { EndLoc = LE; }; + ObjcInterfaceDecl *getClassInterface() const { return ClassInterface; } ObjcInterfaceDecl *getSuperClass() const { return SuperClass; } void setSuperClass(ObjcInterfaceDecl * superCls) { SuperClass = superCls; } - ObjcMethodDecl **getInstanceMethods() const { return InstanceMethods; } - int getNumInstanceMethods() const { return NumInstanceMethods; } + // FIXME: Figure out how to remove the const pointer below. + ObjcMethodDecl *const*getInstanceMethods() const { + return &InstanceMethods[0]; + } + int getNumInstanceMethods() const { return InstanceMethods.size(); } - ObjcMethodDecl **getClassMethods() const { return ClassMethods; } - int getNumClassMethods() const { return NumClassMethods; } + // FIXME: Figure out how to remove the const pointer below. + ObjcMethodDecl *const*getClassMethods() const { + return &ClassMethods[0]; + } + int getNumClassMethods() const { return ClassMethods.size(); } ObjcMethodDecl *lookupInstanceMethod(Selector &Sel); ObjcMethodDecl *lookupClassMethod(Selector &Sel); diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h index 0166e30e7c..7a725d1aca 100644 --- a/include/clang/Parse/Action.h +++ b/include/clang/Parse/Action.h @@ -576,19 +576,19 @@ public: tok::ObjCKeywordKind impKind) { return 0; } - // ActOnAddMethodsToObjcDecl - called to associate methods with an interface, - // protocol, category, or implementation. - virtual void ActOnAddMethodsToObjcDecl( - Scope* S, - DeclTy *ClassDecl, - DeclTy **allMethods, - unsigned allNum, - DeclTy **allProperties, - unsigned NumProperties, - SourceLocation AtEndLoc) { + // ActOnAtEnd - called to mark the @end. For declarations (interfaces, + // protocols, categories), the parser passes all methods/properties. + // For class implementations, these values default to 0. For implementations, + // methods are processed incrementally (by ActOnMethodDeclaration above). + virtual void ActOnAtEnd( + SourceLocation AtEndLoc, + DeclTy *classDecl, + DeclTy **allMethods = 0, + unsigned allNum = 0, + DeclTy **allProperties = 0, + unsigned pNum = 0) { return; } - // ActOnAddObjcProperties - called to build one property AST virtual DeclTy *ActOnAddObjcProperties (SourceLocation AtLoc, DeclTy **allProperties, unsigned NumProperties, ObjcDeclSpec &DS) { diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index 89ebfd8437..d8bde405e5 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -269,8 +269,7 @@ private: DeclTy *ParseObjCAtProtocolDeclaration(SourceLocation atLoc); DeclTy *ObjcImpDecl; - /// Vector is used to collect method decls for each @implementation - llvm::SmallVector<DeclTy*, 32> AllImplMethods; + DeclTy *ParseObjCAtImplementationDeclaration(SourceLocation atLoc); DeclTy *ParseObjCAtEndDeclaration(SourceLocation atLoc); DeclTy *ParseObjCAtAliasDeclaration(SourceLocation atLoc); diff --git a/test/Sema/message.m b/test/Sema/message.m index 517a5f6824..e7717a0485 100644 --- a/test/Sema/message.m +++ b/test/Sema/message.m @@ -6,6 +6,6 @@ @implementation foo - (void) contents {} // No declaration in @interface! -- (void) meth { [self contents]; } // expected-warning {{method '-contents' not found (return type defaults to 'id')}} +- (void) meth { [self contents]; } @end |