| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 1 | //===--- SemaDeclObjC.cpp - Semantic Analysis for ObjC Declarations -------===// | 
 | 2 | // | 
 | 3 | //                     The LLVM Compiler Infrastructure | 
 | 4 | // | 
| Chris Lattner | 0bc735f | 2007-12-29 19:59:25 +0000 | [diff] [blame] | 5 | // This file is distributed under the University of Illinois Open Source | 
 | 6 | // License. See LICENSE.TXT for details. | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 7 | // | 
 | 8 | //===----------------------------------------------------------------------===// | 
 | 9 | // | 
 | 10 | //  This file implements semantic analysis for Objective C declarations. | 
 | 11 | // | 
 | 12 | //===----------------------------------------------------------------------===// | 
 | 13 |  | 
 | 14 | #include "Sema.h" | 
| Douglas Gregor | f06cdae | 2010-01-03 18:01:57 +0000 | [diff] [blame] | 15 | #include "Lookup.h" | 
| Douglas Gregor | f0aaf7a | 2009-04-24 21:10:55 +0000 | [diff] [blame] | 16 | #include "clang/Sema/ExternalSemaSource.h" | 
| Steve Naroff | ca33129 | 2009-03-03 14:49:36 +0000 | [diff] [blame] | 17 | #include "clang/AST/Expr.h" | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 18 | #include "clang/AST/ASTContext.h" | 
 | 19 | #include "clang/AST/DeclObjC.h" | 
| Daniel Dunbar | 12bc692 | 2008-08-11 03:27:53 +0000 | [diff] [blame] | 20 | #include "clang/Parse/DeclSpec.h" | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 21 | using namespace clang; | 
 | 22 |  | 
| Steve Naroff | ebf6443 | 2009-02-28 16:59:13 +0000 | [diff] [blame] | 23 | /// ActOnStartOfObjCMethodDef - This routine sets up parameters; invisible | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 24 | /// and user declared, in the method definition's AST. | 
| Chris Lattner | b28317a | 2009-03-28 19:18:32 +0000 | [diff] [blame] | 25 | void Sema::ActOnStartOfObjCMethodDef(Scope *FnBodyScope, DeclPtrTy D) { | 
| Argyrios Kyrtzidis | 53d0ea5 | 2008-06-28 06:07:14 +0000 | [diff] [blame] | 26 |   assert(getCurMethodDecl() == 0 && "Method parsing confused"); | 
| Chris Lattner | b28317a | 2009-03-28 19:18:32 +0000 | [diff] [blame] | 27 |   ObjCMethodDecl *MDecl = dyn_cast_or_null<ObjCMethodDecl>(D.getAs<Decl>()); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 28 |  | 
| Steve Naroff | 394f3f4 | 2008-07-25 17:57:26 +0000 | [diff] [blame] | 29 |   // If we don't have a valid method decl, simply return. | 
 | 30 |   if (!MDecl) | 
 | 31 |     return; | 
| Steve Naroff | a56f616 | 2007-12-18 01:30:32 +0000 | [diff] [blame] | 32 |  | 
 | 33 |   // Allow the rest of sema to find private method decl implementations. | 
| Douglas Gregor | f8d49f6 | 2009-01-09 17:18:27 +0000 | [diff] [blame] | 34 |   if (MDecl->isInstanceMethod()) | 
| Steve Naroff | a56f616 | 2007-12-18 01:30:32 +0000 | [diff] [blame] | 35 |     AddInstanceMethodToGlobalPool(MDecl); | 
 | 36 |   else | 
 | 37 |     AddFactoryMethodToGlobalPool(MDecl); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 38 |  | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 39 |   // Allow all of Sema to see that we are entering a method definition. | 
| Douglas Gregor | 44b4321 | 2008-12-11 16:49:14 +0000 | [diff] [blame] | 40 |   PushDeclContext(FnBodyScope, MDecl); | 
| Douglas Gregor | 9ea9bdb | 2010-03-01 23:15:13 +0000 | [diff] [blame] | 41 |   PushFunctionScope(); | 
 | 42 |    | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 43 |   // Create Decl objects for each parameter, entrring them in the scope for | 
 | 44 |   // binding to their use. | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 45 |  | 
 | 46 |   // Insert the invisible arguments, self and _cmd! | 
| Fariborz Jahanian | fef30b5 | 2008-12-09 20:23:04 +0000 | [diff] [blame] | 47 |   MDecl->createImplicitParams(Context, MDecl->getClassInterface()); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 48 |  | 
| Daniel Dunbar | 451318c | 2008-08-26 06:07:48 +0000 | [diff] [blame] | 49 |   PushOnScopeChains(MDecl->getSelfDecl(), FnBodyScope); | 
 | 50 |   PushOnScopeChains(MDecl->getCmdDecl(), FnBodyScope); | 
| Chris Lattner | 0442108 | 2008-04-08 04:40:51 +0000 | [diff] [blame] | 51 |  | 
| Chris Lattner | 8123a95 | 2008-04-10 02:22:51 +0000 | [diff] [blame] | 52 |   // Introduce all of the other parameters into this scope. | 
| Chris Lattner | 89951a8 | 2009-02-20 18:43:26 +0000 | [diff] [blame] | 53 |   for (ObjCMethodDecl::param_iterator PI = MDecl->param_begin(), | 
 | 54 |        E = MDecl->param_end(); PI != E; ++PI) | 
 | 55 |     if ((*PI)->getIdentifier()) | 
 | 56 |       PushOnScopeChains(*PI, FnBodyScope); | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 57 | } | 
 | 58 |  | 
| Chris Lattner | b28317a | 2009-03-28 19:18:32 +0000 | [diff] [blame] | 59 | Sema::DeclPtrTy Sema:: | 
| Chris Lattner | 7caeabd | 2008-07-21 22:17:28 +0000 | [diff] [blame] | 60 | ActOnStartClassInterface(SourceLocation AtInterfaceLoc, | 
 | 61 |                          IdentifierInfo *ClassName, SourceLocation ClassLoc, | 
 | 62 |                          IdentifierInfo *SuperName, SourceLocation SuperLoc, | 
| Chris Lattner | b28317a | 2009-03-28 19:18:32 +0000 | [diff] [blame] | 63 |                          const DeclPtrTy *ProtoRefs, unsigned NumProtoRefs, | 
| Douglas Gregor | 18df52b | 2010-01-16 15:02:53 +0000 | [diff] [blame] | 64 |                          const SourceLocation *ProtoLocs,  | 
| Chris Lattner | 7caeabd | 2008-07-21 22:17:28 +0000 | [diff] [blame] | 65 |                          SourceLocation EndProtoLoc, AttributeList *AttrList) { | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 66 |   assert(ClassName && "Missing class identifier"); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 67 |  | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 68 |   // Check for another declaration kind with the same name. | 
| Douglas Gregor | c83c687 | 2010-04-15 22:33:43 +0000 | [diff] [blame] | 69 |   NamedDecl *PrevDecl = LookupSingleName(TUScope, ClassName, ClassLoc, | 
| Douglas Gregor | c0b3964 | 2010-04-15 23:40:53 +0000 | [diff] [blame] | 70 |                                          LookupOrdinaryName, ForRedeclaration); | 
| Douglas Gregor | 72c3f31 | 2008-12-05 18:15:24 +0000 | [diff] [blame] | 71 |  | 
| Ted Kremenek | a526c5c | 2008-01-07 19:49:32 +0000 | [diff] [blame] | 72 |   if (PrevDecl && !isa<ObjCInterfaceDecl>(PrevDecl)) { | 
| Chris Lattner | 3c73c41 | 2008-11-19 08:23:25 +0000 | [diff] [blame] | 73 |     Diag(ClassLoc, diag::err_redefinition_different_kind) << ClassName; | 
| Chris Lattner | 5f4a682 | 2008-11-23 23:12:31 +0000 | [diff] [blame] | 74 |     Diag(PrevDecl->getLocation(), diag::note_previous_definition); | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 75 |   } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 76 |  | 
| Ted Kremenek | a526c5c | 2008-01-07 19:49:32 +0000 | [diff] [blame] | 77 |   ObjCInterfaceDecl* IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl); | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 78 |   if (IDecl) { | 
 | 79 |     // Class already seen. Is it a forward declaration? | 
| Steve Naroff | cfe8bf3 | 2008-11-18 19:15:30 +0000 | [diff] [blame] | 80 |     if (!IDecl->isForwardDecl()) { | 
| Chris Lattner | 1829a6d | 2009-02-23 22:00:08 +0000 | [diff] [blame] | 81 |       IDecl->setInvalidDecl(); | 
| Chris Lattner | d9d22dd | 2008-11-24 05:29:24 +0000 | [diff] [blame] | 82 |       Diag(AtInterfaceLoc, diag::err_duplicate_class_def)<<IDecl->getDeclName(); | 
| Chris Lattner | b8b96af | 2008-11-23 22:46:27 +0000 | [diff] [blame] | 83 |       Diag(IDecl->getLocation(), diag::note_previous_definition); | 
 | 84 |  | 
| Steve Naroff | cfe8bf3 | 2008-11-18 19:15:30 +0000 | [diff] [blame] | 85 |       // Return the previous class interface. | 
 | 86 |       // FIXME: don't leak the objects passed in! | 
| Chris Lattner | b28317a | 2009-03-28 19:18:32 +0000 | [diff] [blame] | 87 |       return DeclPtrTy::make(IDecl); | 
| Steve Naroff | cfe8bf3 | 2008-11-18 19:15:30 +0000 | [diff] [blame] | 88 |     } else { | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 89 |       IDecl->setLocation(AtInterfaceLoc); | 
 | 90 |       IDecl->setForwardDecl(false); | 
| Steve Naroff | 8b26cbd | 2009-09-11 00:12:01 +0000 | [diff] [blame] | 91 |       IDecl->setClassLoc(ClassLoc); | 
| Ted Kremenek | c32b1d8 | 2009-11-17 22:58:30 +0000 | [diff] [blame] | 92 |        | 
 | 93 |       // Since this ObjCInterfaceDecl was created by a forward declaration, | 
 | 94 |       // we now add it to the DeclContext since it wasn't added before | 
 | 95 |       // (see ActOnForwardClassDeclaration). | 
| Douglas Gregor | 78713d8 | 2010-04-09 21:30:38 +0000 | [diff] [blame] | 96 |       IDecl->setLexicalDeclContext(CurContext); | 
| Ted Kremenek | c32b1d8 | 2009-11-17 22:58:30 +0000 | [diff] [blame] | 97 |       CurContext->addDecl(IDecl); | 
 | 98 |        | 
| Fariborz Jahanian | 5f8f857 | 2009-11-17 19:08:08 +0000 | [diff] [blame] | 99 |       if (AttrList) | 
 | 100 |         ProcessDeclAttributeList(TUScope, IDecl, AttrList); | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 101 |     } | 
| Chris Lattner | b752f28 | 2008-07-21 07:06:49 +0000 | [diff] [blame] | 102 |   } else { | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 103 |     IDecl = ObjCInterfaceDecl::Create(Context, CurContext, AtInterfaceLoc, | 
| Steve Naroff | d6a07aa | 2008-04-11 19:35:35 +0000 | [diff] [blame] | 104 |                                       ClassName, ClassLoc); | 
| Daniel Dunbar | f641492 | 2008-08-20 18:02:42 +0000 | [diff] [blame] | 105 |     if (AttrList) | 
| Douglas Gregor | 9cdda0c | 2009-06-17 21:51:59 +0000 | [diff] [blame] | 106 |       ProcessDeclAttributeList(TUScope, IDecl, AttrList); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 107 |  | 
| Steve Naroff | a7503a7 | 2009-04-23 15:15:40 +0000 | [diff] [blame] | 108 |     PushOnScopeChains(IDecl, TUScope); | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 109 |   } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 110 |  | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 111 |   if (SuperName) { | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 112 |     // Check if a different kind of symbol declared in this scope. | 
| Douglas Gregor | c83c687 | 2010-04-15 22:33:43 +0000 | [diff] [blame] | 113 |     PrevDecl = LookupSingleName(TUScope, SuperName, SuperLoc, | 
 | 114 |                                 LookupOrdinaryName); | 
| Douglas Gregor | f06cdae | 2010-01-03 18:01:57 +0000 | [diff] [blame] | 115 |  | 
 | 116 |     if (!PrevDecl) { | 
 | 117 |       // Try to correct for a typo in the superclass name. | 
 | 118 |       LookupResult R(*this, SuperName, SuperLoc, LookupOrdinaryName); | 
| Douglas Gregor | aaf8716 | 2010-04-14 20:04:41 +0000 | [diff] [blame] | 119 |       if (CorrectTypo(R, TUScope, 0, 0, false, CTC_NoKeywords) && | 
| Douglas Gregor | f06cdae | 2010-01-03 18:01:57 +0000 | [diff] [blame] | 120 |           (PrevDecl = R.getAsSingle<ObjCInterfaceDecl>())) { | 
 | 121 |         Diag(SuperLoc, diag::err_undef_superclass_suggest) | 
 | 122 |           << SuperName << ClassName << PrevDecl->getDeclName(); | 
| Douglas Gregor | 67dd1d4 | 2010-01-07 00:17:44 +0000 | [diff] [blame] | 123 |         Diag(PrevDecl->getLocation(), diag::note_previous_decl) | 
 | 124 |           << PrevDecl->getDeclName(); | 
| Douglas Gregor | f06cdae | 2010-01-03 18:01:57 +0000 | [diff] [blame] | 125 |       } | 
 | 126 |     } | 
 | 127 |  | 
| Fariborz Jahanian | fdee089 | 2009-07-09 22:08:26 +0000 | [diff] [blame] | 128 |     if (PrevDecl == IDecl) { | 
 | 129 |       Diag(SuperLoc, diag::err_recursive_superclass) | 
 | 130 |         << SuperName << ClassName << SourceRange(AtInterfaceLoc, ClassLoc); | 
 | 131 |       IDecl->setLocEnd(ClassLoc); | 
| Mike Stump | ac5fc7c | 2009-08-04 21:02:39 +0000 | [diff] [blame] | 132 |     } else { | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 133 |       ObjCInterfaceDecl *SuperClassDecl = | 
| Fariborz Jahanian | fdee089 | 2009-07-09 22:08:26 +0000 | [diff] [blame] | 134 |                                 dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl); | 
| Chris Lattner | 3c73c41 | 2008-11-19 08:23:25 +0000 | [diff] [blame] | 135 |  | 
| Fariborz Jahanian | fdee089 | 2009-07-09 22:08:26 +0000 | [diff] [blame] | 136 |       // Diagnose classes that inherit from deprecated classes. | 
 | 137 |       if (SuperClassDecl) | 
 | 138 |         (void)DiagnoseUseOfDecl(SuperClassDecl, SuperLoc); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 139 |  | 
| Fariborz Jahanian | fdee089 | 2009-07-09 22:08:26 +0000 | [diff] [blame] | 140 |       if (PrevDecl && SuperClassDecl == 0) { | 
 | 141 |         // The previous declaration was not a class decl. Check if we have a | 
 | 142 |         // typedef. If we do, get the underlying class type. | 
 | 143 |         if (const TypedefDecl *TDecl = dyn_cast_or_null<TypedefDecl>(PrevDecl)) { | 
 | 144 |           QualType T = TDecl->getUnderlyingType(); | 
| John McCall | c12c5bb | 2010-05-15 11:32:37 +0000 | [diff] [blame] | 145 |           if (T->isObjCObjectType()) { | 
 | 146 |             if (NamedDecl *IDecl = T->getAs<ObjCObjectType>()->getInterface()) | 
| Fariborz Jahanian | fdee089 | 2009-07-09 22:08:26 +0000 | [diff] [blame] | 147 |               SuperClassDecl = dyn_cast<ObjCInterfaceDecl>(IDecl); | 
 | 148 |           } | 
 | 149 |         } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 150 |  | 
| Fariborz Jahanian | fdee089 | 2009-07-09 22:08:26 +0000 | [diff] [blame] | 151 |         // This handles the following case: | 
 | 152 |         // | 
 | 153 |         // typedef int SuperClass; | 
 | 154 |         // @interface MyClass : SuperClass {} @end | 
 | 155 |         // | 
 | 156 |         if (!SuperClassDecl) { | 
 | 157 |           Diag(SuperLoc, diag::err_redefinition_different_kind) << SuperName; | 
 | 158 |           Diag(PrevDecl->getLocation(), diag::note_previous_definition); | 
| Steve Naroff | 818cb9e | 2009-02-04 17:14:05 +0000 | [diff] [blame] | 159 |         } | 
 | 160 |       } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 161 |  | 
| Fariborz Jahanian | fdee089 | 2009-07-09 22:08:26 +0000 | [diff] [blame] | 162 |       if (!dyn_cast_or_null<TypedefDecl>(PrevDecl)) { | 
 | 163 |         if (!SuperClassDecl) | 
 | 164 |           Diag(SuperLoc, diag::err_undef_superclass) | 
 | 165 |             << SuperName << ClassName << SourceRange(AtInterfaceLoc, ClassLoc); | 
 | 166 |         else if (SuperClassDecl->isForwardDecl()) | 
 | 167 |           Diag(SuperLoc, diag::err_undef_superclass) | 
 | 168 |             << SuperClassDecl->getDeclName() << ClassName | 
 | 169 |             << SourceRange(AtInterfaceLoc, ClassLoc); | 
| Steve Naroff | 818cb9e | 2009-02-04 17:14:05 +0000 | [diff] [blame] | 170 |       } | 
| Fariborz Jahanian | fdee089 | 2009-07-09 22:08:26 +0000 | [diff] [blame] | 171 |       IDecl->setSuperClass(SuperClassDecl); | 
 | 172 |       IDecl->setSuperClassLoc(SuperLoc); | 
 | 173 |       IDecl->setLocEnd(SuperLoc); | 
| Steve Naroff | 818cb9e | 2009-02-04 17:14:05 +0000 | [diff] [blame] | 174 |     } | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 175 |   } else { // we have a root class. | 
 | 176 |     IDecl->setLocEnd(ClassLoc); | 
 | 177 |   } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 178 |  | 
| Steve Naroff | cfe8bf3 | 2008-11-18 19:15:30 +0000 | [diff] [blame] | 179 |   /// Check then save referenced protocols. | 
| Chris Lattner | 06036d3 | 2008-07-26 04:13:19 +0000 | [diff] [blame] | 180 |   if (NumProtoRefs) { | 
| Chris Lattner | 38af2de | 2009-02-20 21:35:13 +0000 | [diff] [blame] | 181 |     IDecl->setProtocolList((ObjCProtocolDecl**)ProtoRefs, NumProtoRefs, | 
| Douglas Gregor | 18df52b | 2010-01-16 15:02:53 +0000 | [diff] [blame] | 182 |                            ProtoLocs, Context); | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 183 |     IDecl->setLocEnd(EndProtoLoc); | 
 | 184 |   } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 185 |  | 
| Anders Carlsson | 1528145 | 2008-11-04 16:57:32 +0000 | [diff] [blame] | 186 |   CheckObjCDeclScope(IDecl); | 
| Chris Lattner | b28317a | 2009-03-28 19:18:32 +0000 | [diff] [blame] | 187 |   return DeclPtrTy::make(IDecl); | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 188 | } | 
 | 189 |  | 
 | 190 | /// ActOnCompatiblityAlias - this action is called after complete parsing of | 
| Daniel Dunbar | 7ad1b1f | 2008-09-04 20:01:15 +0000 | [diff] [blame] | 191 | /// @compatibility_alias declaration. It sets up the alias relationships. | 
| Chris Lattner | b28317a | 2009-03-28 19:18:32 +0000 | [diff] [blame] | 192 | Sema::DeclPtrTy Sema::ActOnCompatiblityAlias(SourceLocation AtLoc, | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 193 |                                              IdentifierInfo *AliasName, | 
| Chris Lattner | b28317a | 2009-03-28 19:18:32 +0000 | [diff] [blame] | 194 |                                              SourceLocation AliasLocation, | 
 | 195 |                                              IdentifierInfo *ClassName, | 
 | 196 |                                              SourceLocation ClassLocation) { | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 197 |   // Look for previous declaration of alias name | 
| Douglas Gregor | c83c687 | 2010-04-15 22:33:43 +0000 | [diff] [blame] | 198 |   NamedDecl *ADecl = LookupSingleName(TUScope, AliasName, AliasLocation, | 
| Douglas Gregor | c0b3964 | 2010-04-15 23:40:53 +0000 | [diff] [blame] | 199 |                                       LookupOrdinaryName, ForRedeclaration); | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 200 |   if (ADecl) { | 
| Chris Lattner | 8b265bd | 2008-11-23 23:20:13 +0000 | [diff] [blame] | 201 |     if (isa<ObjCCompatibleAliasDecl>(ADecl)) | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 202 |       Diag(AliasLocation, diag::warn_previous_alias_decl); | 
| Chris Lattner | 8b265bd | 2008-11-23 23:20:13 +0000 | [diff] [blame] | 203 |     else | 
| Chris Lattner | 3c73c41 | 2008-11-19 08:23:25 +0000 | [diff] [blame] | 204 |       Diag(AliasLocation, diag::err_conflicting_aliasing_type) << AliasName; | 
| Chris Lattner | 8b265bd | 2008-11-23 23:20:13 +0000 | [diff] [blame] | 205 |     Diag(ADecl->getLocation(), diag::note_previous_declaration); | 
| Chris Lattner | b28317a | 2009-03-28 19:18:32 +0000 | [diff] [blame] | 206 |     return DeclPtrTy(); | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 207 |   } | 
 | 208 |   // Check for class declaration | 
| Douglas Gregor | c83c687 | 2010-04-15 22:33:43 +0000 | [diff] [blame] | 209 |   NamedDecl *CDeclU = LookupSingleName(TUScope, ClassName, ClassLocation, | 
| Douglas Gregor | c0b3964 | 2010-04-15 23:40:53 +0000 | [diff] [blame] | 210 |                                        LookupOrdinaryName, ForRedeclaration); | 
| Fariborz Jahanian | 305c658 | 2009-01-08 01:10:55 +0000 | [diff] [blame] | 211 |   if (const TypedefDecl *TDecl = dyn_cast_or_null<TypedefDecl>(CDeclU)) { | 
 | 212 |     QualType T = TDecl->getUnderlyingType(); | 
| John McCall | c12c5bb | 2010-05-15 11:32:37 +0000 | [diff] [blame] | 213 |     if (T->isObjCObjectType()) { | 
 | 214 |       if (NamedDecl *IDecl = T->getAs<ObjCObjectType>()->getInterface()) { | 
| Fariborz Jahanian | 305c658 | 2009-01-08 01:10:55 +0000 | [diff] [blame] | 215 |         ClassName = IDecl->getIdentifier(); | 
| Douglas Gregor | c83c687 | 2010-04-15 22:33:43 +0000 | [diff] [blame] | 216 |         CDeclU = LookupSingleName(TUScope, ClassName, ClassLocation, | 
| Douglas Gregor | c0b3964 | 2010-04-15 23:40:53 +0000 | [diff] [blame] | 217 |                                   LookupOrdinaryName, ForRedeclaration); | 
| Fariborz Jahanian | 305c658 | 2009-01-08 01:10:55 +0000 | [diff] [blame] | 218 |       } | 
 | 219 |     } | 
 | 220 |   } | 
| Chris Lattner | f8d17a5 | 2008-03-16 21:17:37 +0000 | [diff] [blame] | 221 |   ObjCInterfaceDecl *CDecl = dyn_cast_or_null<ObjCInterfaceDecl>(CDeclU); | 
 | 222 |   if (CDecl == 0) { | 
| Chris Lattner | 3c73c41 | 2008-11-19 08:23:25 +0000 | [diff] [blame] | 223 |     Diag(ClassLocation, diag::warn_undef_interface) << ClassName; | 
| Chris Lattner | f8d17a5 | 2008-03-16 21:17:37 +0000 | [diff] [blame] | 224 |     if (CDeclU) | 
| Chris Lattner | 8b265bd | 2008-11-23 23:20:13 +0000 | [diff] [blame] | 225 |       Diag(CDeclU->getLocation(), diag::note_previous_declaration); | 
| Chris Lattner | b28317a | 2009-03-28 19:18:32 +0000 | [diff] [blame] | 226 |     return DeclPtrTy(); | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 227 |   } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 228 |  | 
| Chris Lattner | f8d17a5 | 2008-03-16 21:17:37 +0000 | [diff] [blame] | 229 |   // Everything checked out, instantiate a new alias declaration AST. | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 230 |   ObjCCompatibleAliasDecl *AliasDecl = | 
| Douglas Gregor | d043410 | 2009-01-09 00:49:46 +0000 | [diff] [blame] | 231 |     ObjCCompatibleAliasDecl::Create(Context, CurContext, AtLoc, AliasName, CDecl); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 232 |  | 
| Anders Carlsson | 1528145 | 2008-11-04 16:57:32 +0000 | [diff] [blame] | 233 |   if (!CheckObjCDeclScope(AliasDecl)) | 
| Douglas Gregor | 516ff43 | 2009-04-24 02:57:34 +0000 | [diff] [blame] | 234 |     PushOnScopeChains(AliasDecl, TUScope); | 
| Douglas Gregor | d043410 | 2009-01-09 00:49:46 +0000 | [diff] [blame] | 235 |  | 
| Chris Lattner | b28317a | 2009-03-28 19:18:32 +0000 | [diff] [blame] | 236 |   return DeclPtrTy::make(AliasDecl); | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 237 | } | 
 | 238 |  | 
| Steve Naroff | 61d6852 | 2009-03-05 15:22:01 +0000 | [diff] [blame] | 239 | void Sema::CheckForwardProtocolDeclarationForCircularDependency( | 
 | 240 |   IdentifierInfo *PName, | 
 | 241 |   SourceLocation &Ploc, SourceLocation PrevLoc, | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 242 |   const ObjCList<ObjCProtocolDecl> &PList) { | 
| Steve Naroff | 61d6852 | 2009-03-05 15:22:01 +0000 | [diff] [blame] | 243 |   for (ObjCList<ObjCProtocolDecl>::iterator I = PList.begin(), | 
 | 244 |        E = PList.end(); I != E; ++I) { | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 245 |  | 
| Douglas Gregor | c83c687 | 2010-04-15 22:33:43 +0000 | [diff] [blame] | 246 |     if (ObjCProtocolDecl *PDecl = LookupProtocol((*I)->getIdentifier(), | 
 | 247 |                                                  Ploc)) { | 
| Steve Naroff | 61d6852 | 2009-03-05 15:22:01 +0000 | [diff] [blame] | 248 |       if (PDecl->getIdentifier() == PName) { | 
 | 249 |         Diag(Ploc, diag::err_protocol_has_circular_dependency); | 
 | 250 |         Diag(PrevLoc, diag::note_previous_definition); | 
 | 251 |       } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 252 |       CheckForwardProtocolDeclarationForCircularDependency(PName, Ploc, | 
| Steve Naroff | 61d6852 | 2009-03-05 15:22:01 +0000 | [diff] [blame] | 253 |         PDecl->getLocation(), PDecl->getReferencedProtocols()); | 
 | 254 |     } | 
 | 255 |   } | 
 | 256 | } | 
 | 257 |  | 
| Chris Lattner | b28317a | 2009-03-28 19:18:32 +0000 | [diff] [blame] | 258 | Sema::DeclPtrTy | 
| Chris Lattner | e13b959 | 2008-07-26 04:03:38 +0000 | [diff] [blame] | 259 | Sema::ActOnStartProtocolInterface(SourceLocation AtProtoInterfaceLoc, | 
 | 260 |                                   IdentifierInfo *ProtocolName, | 
 | 261 |                                   SourceLocation ProtocolLoc, | 
| Chris Lattner | b28317a | 2009-03-28 19:18:32 +0000 | [diff] [blame] | 262 |                                   const DeclPtrTy *ProtoRefs, | 
| Chris Lattner | e13b959 | 2008-07-26 04:03:38 +0000 | [diff] [blame] | 263 |                                   unsigned NumProtoRefs, | 
| Douglas Gregor | 18df52b | 2010-01-16 15:02:53 +0000 | [diff] [blame] | 264 |                                   const SourceLocation *ProtoLocs, | 
| Daniel Dunbar | 246e70f | 2008-09-26 04:48:09 +0000 | [diff] [blame] | 265 |                                   SourceLocation EndProtoLoc, | 
 | 266 |                                   AttributeList *AttrList) { | 
 | 267 |   // FIXME: Deal with AttrList. | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 268 |   assert(ProtocolName && "Missing protocol identifier"); | 
| Douglas Gregor | c83c687 | 2010-04-15 22:33:43 +0000 | [diff] [blame] | 269 |   ObjCProtocolDecl *PDecl = LookupProtocol(ProtocolName, ProtocolLoc); | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 270 |   if (PDecl) { | 
 | 271 |     // Protocol already seen. Better be a forward protocol declaration | 
| Chris Lattner | 439e71f | 2008-03-16 01:25:17 +0000 | [diff] [blame] | 272 |     if (!PDecl->isForwardDecl()) { | 
| Fariborz Jahanian | e2573e5 | 2009-04-06 23:43:32 +0000 | [diff] [blame] | 273 |       Diag(ProtocolLoc, diag::warn_duplicate_protocol_def) << ProtocolName; | 
| Chris Lattner | b8b96af | 2008-11-23 22:46:27 +0000 | [diff] [blame] | 274 |       Diag(PDecl->getLocation(), diag::note_previous_definition); | 
| Chris Lattner | 439e71f | 2008-03-16 01:25:17 +0000 | [diff] [blame] | 275 |       // Just return the protocol we already had. | 
 | 276 |       // FIXME: don't leak the objects passed in! | 
| Chris Lattner | b28317a | 2009-03-28 19:18:32 +0000 | [diff] [blame] | 277 |       return DeclPtrTy::make(PDecl); | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 278 |     } | 
| Steve Naroff | 61d6852 | 2009-03-05 15:22:01 +0000 | [diff] [blame] | 279 |     ObjCList<ObjCProtocolDecl> PList; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 280 |     PList.set((ObjCProtocolDecl *const*)ProtoRefs, NumProtoRefs, Context); | 
| Steve Naroff | 61d6852 | 2009-03-05 15:22:01 +0000 | [diff] [blame] | 281 |     CheckForwardProtocolDeclarationForCircularDependency( | 
 | 282 |       ProtocolName, ProtocolLoc, PDecl->getLocation(), PList); | 
 | 283 |     PList.Destroy(Context); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 284 |  | 
| Steve Naroff | f11b508 | 2008-08-13 16:39:22 +0000 | [diff] [blame] | 285 |     // Make sure the cached decl gets a valid start location. | 
 | 286 |     PDecl->setLocation(AtProtoInterfaceLoc); | 
| Chris Lattner | 439e71f | 2008-03-16 01:25:17 +0000 | [diff] [blame] | 287 |     PDecl->setForwardDecl(false); | 
| Chris Lattner | 439e71f | 2008-03-16 01:25:17 +0000 | [diff] [blame] | 288 |   } else { | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 289 |     PDecl = ObjCProtocolDecl::Create(Context, CurContext, | 
| Douglas Gregor | d043410 | 2009-01-09 00:49:46 +0000 | [diff] [blame] | 290 |                                      AtProtoInterfaceLoc,ProtocolName); | 
| Douglas Gregor | 6e378de | 2009-04-23 23:18:26 +0000 | [diff] [blame] | 291 |     PushOnScopeChains(PDecl, TUScope); | 
| Chris Lattner | c858105 | 2008-03-16 20:19:15 +0000 | [diff] [blame] | 292 |     PDecl->setForwardDecl(false); | 
| Chris Lattner | cca59d7 | 2008-03-16 01:23:04 +0000 | [diff] [blame] | 293 |   } | 
| Fariborz Jahanian | bc1c877 | 2008-12-17 01:07:27 +0000 | [diff] [blame] | 294 |   if (AttrList) | 
| Douglas Gregor | 9cdda0c | 2009-06-17 21:51:59 +0000 | [diff] [blame] | 295 |     ProcessDeclAttributeList(TUScope, PDecl, AttrList); | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 296 |   if (NumProtoRefs) { | 
| Chris Lattner | c858105 | 2008-03-16 20:19:15 +0000 | [diff] [blame] | 297 |     /// Check then save referenced protocols. | 
| Douglas Gregor | 18df52b | 2010-01-16 15:02:53 +0000 | [diff] [blame] | 298 |     PDecl->setProtocolList((ObjCProtocolDecl**)ProtoRefs, NumProtoRefs, | 
 | 299 |                            ProtoLocs, Context); | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 300 |     PDecl->setLocEnd(EndProtoLoc); | 
 | 301 |   } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 302 |  | 
 | 303 |   CheckObjCDeclScope(PDecl); | 
| Chris Lattner | b28317a | 2009-03-28 19:18:32 +0000 | [diff] [blame] | 304 |   return DeclPtrTy::make(PDecl); | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 305 | } | 
 | 306 |  | 
 | 307 | /// FindProtocolDeclaration - This routine looks up protocols and | 
| Daniel Dunbar | 7ad1b1f | 2008-09-04 20:01:15 +0000 | [diff] [blame] | 308 | /// issues an error if they are not declared. It returns list of | 
 | 309 | /// protocol declarations in its 'Protocols' argument. | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 310 | void | 
| Chris Lattner | e13b959 | 2008-07-26 04:03:38 +0000 | [diff] [blame] | 311 | Sema::FindProtocolDeclaration(bool WarnOnDeclarations, | 
| Chris Lattner | 7caeabd | 2008-07-21 22:17:28 +0000 | [diff] [blame] | 312 |                               const IdentifierLocPair *ProtocolId, | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 313 |                               unsigned NumProtocols, | 
| Chris Lattner | b28317a | 2009-03-28 19:18:32 +0000 | [diff] [blame] | 314 |                               llvm::SmallVectorImpl<DeclPtrTy> &Protocols) { | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 315 |   for (unsigned i = 0; i != NumProtocols; ++i) { | 
| Douglas Gregor | c83c687 | 2010-04-15 22:33:43 +0000 | [diff] [blame] | 316 |     ObjCProtocolDecl *PDecl = LookupProtocol(ProtocolId[i].first, | 
 | 317 |                                              ProtocolId[i].second); | 
| Chris Lattner | eacc392 | 2008-07-26 03:47:43 +0000 | [diff] [blame] | 318 |     if (!PDecl) { | 
| Douglas Gregor | f06cdae | 2010-01-03 18:01:57 +0000 | [diff] [blame] | 319 |       LookupResult R(*this, ProtocolId[i].first, ProtocolId[i].second, | 
 | 320 |                      LookupObjCProtocolName); | 
| Douglas Gregor | aaf8716 | 2010-04-14 20:04:41 +0000 | [diff] [blame] | 321 |       if (CorrectTypo(R, TUScope, 0, 0, false, CTC_NoKeywords) && | 
| Douglas Gregor | f06cdae | 2010-01-03 18:01:57 +0000 | [diff] [blame] | 322 |           (PDecl = R.getAsSingle<ObjCProtocolDecl>())) { | 
 | 323 |         Diag(ProtocolId[i].second, diag::err_undeclared_protocol_suggest) | 
 | 324 |           << ProtocolId[i].first << R.getLookupName(); | 
| Douglas Gregor | 67dd1d4 | 2010-01-07 00:17:44 +0000 | [diff] [blame] | 325 |         Diag(PDecl->getLocation(), diag::note_previous_decl) | 
 | 326 |           << PDecl->getDeclName(); | 
| Douglas Gregor | f06cdae | 2010-01-03 18:01:57 +0000 | [diff] [blame] | 327 |       } | 
 | 328 |     } | 
 | 329 |  | 
 | 330 |     if (!PDecl) { | 
| Chris Lattner | fa25bbb | 2008-11-19 05:08:23 +0000 | [diff] [blame] | 331 |       Diag(ProtocolId[i].second, diag::err_undeclared_protocol) | 
| Chris Lattner | 3c73c41 | 2008-11-19 08:23:25 +0000 | [diff] [blame] | 332 |         << ProtocolId[i].first; | 
| Chris Lattner | eacc392 | 2008-07-26 03:47:43 +0000 | [diff] [blame] | 333 |       continue; | 
 | 334 |     } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 335 |  | 
| Douglas Gregor | 48f3bb9 | 2009-02-18 21:56:37 +0000 | [diff] [blame] | 336 |     (void)DiagnoseUseOfDecl(PDecl, ProtocolId[i].second); | 
| Chris Lattner | eacc392 | 2008-07-26 03:47:43 +0000 | [diff] [blame] | 337 |  | 
 | 338 |     // If this is a forward declaration and we are supposed to warn in this | 
 | 339 |     // case, do it. | 
 | 340 |     if (WarnOnDeclarations && PDecl->isForwardDecl()) | 
| Chris Lattner | fa25bbb | 2008-11-19 05:08:23 +0000 | [diff] [blame] | 341 |       Diag(ProtocolId[i].second, diag::warn_undef_protocolref) | 
| Chris Lattner | 3c73c41 | 2008-11-19 08:23:25 +0000 | [diff] [blame] | 342 |         << ProtocolId[i].first; | 
| Chris Lattner | b28317a | 2009-03-28 19:18:32 +0000 | [diff] [blame] | 343 |     Protocols.push_back(DeclPtrTy::make(PDecl)); | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 344 |   } | 
 | 345 | } | 
 | 346 |  | 
| Fariborz Jahanian | 78c39c7 | 2009-03-02 19:06:08 +0000 | [diff] [blame] | 347 | /// DiagnoseClassExtensionDupMethods - Check for duplicate declaration of | 
| Fariborz Jahanian | b7f95f5 | 2009-03-02 19:05:07 +0000 | [diff] [blame] | 348 | /// a class method in its extension. | 
 | 349 | /// | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 350 | void Sema::DiagnoseClassExtensionDupMethods(ObjCCategoryDecl *CAT, | 
| Fariborz Jahanian | b7f95f5 | 2009-03-02 19:05:07 +0000 | [diff] [blame] | 351 |                                             ObjCInterfaceDecl *ID) { | 
 | 352 |   if (!ID) | 
 | 353 |     return;  // Possibly due to previous error | 
 | 354 |  | 
 | 355 |   llvm::DenseMap<Selector, const ObjCMethodDecl*> MethodMap; | 
| Argyrios Kyrtzidis | 17945a0 | 2009-06-30 02:36:12 +0000 | [diff] [blame] | 356 |   for (ObjCInterfaceDecl::method_iterator i = ID->meth_begin(), | 
 | 357 |        e =  ID->meth_end(); i != e; ++i) { | 
| Fariborz Jahanian | b7f95f5 | 2009-03-02 19:05:07 +0000 | [diff] [blame] | 358 |     ObjCMethodDecl *MD = *i; | 
 | 359 |     MethodMap[MD->getSelector()] = MD; | 
 | 360 |   } | 
 | 361 |  | 
 | 362 |   if (MethodMap.empty()) | 
 | 363 |     return; | 
| Argyrios Kyrtzidis | 17945a0 | 2009-06-30 02:36:12 +0000 | [diff] [blame] | 364 |   for (ObjCCategoryDecl::method_iterator i = CAT->meth_begin(), | 
 | 365 |        e =  CAT->meth_end(); i != e; ++i) { | 
| Fariborz Jahanian | b7f95f5 | 2009-03-02 19:05:07 +0000 | [diff] [blame] | 366 |     ObjCMethodDecl *Method = *i; | 
 | 367 |     const ObjCMethodDecl *&PrevMethod = MethodMap[Method->getSelector()]; | 
 | 368 |     if (PrevMethod && !MatchTwoMethodDeclarations(Method, PrevMethod)) { | 
 | 369 |       Diag(Method->getLocation(), diag::err_duplicate_method_decl) | 
 | 370 |             << Method->getDeclName(); | 
 | 371 |       Diag(PrevMethod->getLocation(), diag::note_previous_declaration); | 
 | 372 |     } | 
 | 373 |   } | 
 | 374 | } | 
 | 375 |  | 
| Chris Lattner | 58fe03b | 2009-04-12 08:43:13 +0000 | [diff] [blame] | 376 | /// ActOnForwardProtocolDeclaration - Handle @protocol foo; | 
| Chris Lattner | b28317a | 2009-03-28 19:18:32 +0000 | [diff] [blame] | 377 | Action::DeclPtrTy | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 378 | Sema::ActOnForwardProtocolDeclaration(SourceLocation AtProtocolLoc, | 
| Chris Lattner | 7caeabd | 2008-07-21 22:17:28 +0000 | [diff] [blame] | 379 |                                       const IdentifierLocPair *IdentList, | 
| Fariborz Jahanian | bc1c877 | 2008-12-17 01:07:27 +0000 | [diff] [blame] | 380 |                                       unsigned NumElts, | 
 | 381 |                                       AttributeList *attrList) { | 
| Ted Kremenek | a526c5c | 2008-01-07 19:49:32 +0000 | [diff] [blame] | 382 |   llvm::SmallVector<ObjCProtocolDecl*, 32> Protocols; | 
| Douglas Gregor | 18df52b | 2010-01-16 15:02:53 +0000 | [diff] [blame] | 383 |   llvm::SmallVector<SourceLocation, 8> ProtoLocs; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 384 |  | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 385 |   for (unsigned i = 0; i != NumElts; ++i) { | 
| Chris Lattner | 7caeabd | 2008-07-21 22:17:28 +0000 | [diff] [blame] | 386 |     IdentifierInfo *Ident = IdentList[i].first; | 
| Douglas Gregor | c83c687 | 2010-04-15 22:33:43 +0000 | [diff] [blame] | 387 |     ObjCProtocolDecl *PDecl = LookupProtocol(Ident, IdentList[i].second); | 
| Douglas Gregor | d043410 | 2009-01-09 00:49:46 +0000 | [diff] [blame] | 388 |     if (PDecl == 0) { // Not already seen? | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 389 |       PDecl = ObjCProtocolDecl::Create(Context, CurContext, | 
| Douglas Gregor | d043410 | 2009-01-09 00:49:46 +0000 | [diff] [blame] | 390 |                                        IdentList[i].second, Ident); | 
| Douglas Gregor | 6e378de | 2009-04-23 23:18:26 +0000 | [diff] [blame] | 391 |       PushOnScopeChains(PDecl, TUScope); | 
| Douglas Gregor | d043410 | 2009-01-09 00:49:46 +0000 | [diff] [blame] | 392 |     } | 
| Fariborz Jahanian | bc1c877 | 2008-12-17 01:07:27 +0000 | [diff] [blame] | 393 |     if (attrList) | 
| Douglas Gregor | 9cdda0c | 2009-06-17 21:51:59 +0000 | [diff] [blame] | 394 |       ProcessDeclAttributeList(TUScope, PDecl, attrList); | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 395 |     Protocols.push_back(PDecl); | 
| Douglas Gregor | 18df52b | 2010-01-16 15:02:53 +0000 | [diff] [blame] | 396 |     ProtoLocs.push_back(IdentList[i].second); | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 397 |   } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 398 |  | 
 | 399 |   ObjCForwardProtocolDecl *PDecl = | 
| Douglas Gregor | d043410 | 2009-01-09 00:49:46 +0000 | [diff] [blame] | 400 |     ObjCForwardProtocolDecl::Create(Context, CurContext, AtProtocolLoc, | 
| Douglas Gregor | 18df52b | 2010-01-16 15:02:53 +0000 | [diff] [blame] | 401 |                                     Protocols.data(), Protocols.size(), | 
 | 402 |                                     ProtoLocs.data()); | 
| Argyrios Kyrtzidis | 17945a0 | 2009-06-30 02:36:12 +0000 | [diff] [blame] | 403 |   CurContext->addDecl(PDecl); | 
| Anders Carlsson | 1528145 | 2008-11-04 16:57:32 +0000 | [diff] [blame] | 404 |   CheckObjCDeclScope(PDecl); | 
| Chris Lattner | b28317a | 2009-03-28 19:18:32 +0000 | [diff] [blame] | 405 |   return DeclPtrTy::make(PDecl); | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 406 | } | 
 | 407 |  | 
| Chris Lattner | b28317a | 2009-03-28 19:18:32 +0000 | [diff] [blame] | 408 | Sema::DeclPtrTy Sema:: | 
| Chris Lattner | 7caeabd | 2008-07-21 22:17:28 +0000 | [diff] [blame] | 409 | ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc, | 
 | 410 |                             IdentifierInfo *ClassName, SourceLocation ClassLoc, | 
 | 411 |                             IdentifierInfo *CategoryName, | 
 | 412 |                             SourceLocation CategoryLoc, | 
| Chris Lattner | b28317a | 2009-03-28 19:18:32 +0000 | [diff] [blame] | 413 |                             const DeclPtrTy *ProtoRefs, | 
| Chris Lattner | 7caeabd | 2008-07-21 22:17:28 +0000 | [diff] [blame] | 414 |                             unsigned NumProtoRefs, | 
| Douglas Gregor | 18df52b | 2010-01-16 15:02:53 +0000 | [diff] [blame] | 415 |                             const SourceLocation *ProtoLocs, | 
| Chris Lattner | 7caeabd | 2008-07-21 22:17:28 +0000 | [diff] [blame] | 416 |                             SourceLocation EndProtoLoc) { | 
| Fariborz Jahanian | 2576061 | 2010-02-15 21:55:26 +0000 | [diff] [blame] | 417 |   ObjCCategoryDecl *CDecl = 0; | 
| Douglas Gregor | c83c687 | 2010-04-15 22:33:43 +0000 | [diff] [blame] | 418 |   ObjCInterfaceDecl *IDecl = getObjCInterfaceDecl(ClassName, ClassLoc, true); | 
| Ted Kremenek | 09b6897 | 2010-02-23 19:39:46 +0000 | [diff] [blame] | 419 |  | 
 | 420 |   /// Check that class of this category is already completely declared. | 
 | 421 |   if (!IDecl || IDecl->isForwardDecl()) { | 
 | 422 |     // Create an invalid ObjCCategoryDecl to serve as context for | 
 | 423 |     // the enclosing method declarations.  We mark the decl invalid | 
 | 424 |     // to make it clear that this isn't a valid AST. | 
 | 425 |     CDecl = ObjCCategoryDecl::Create(Context, CurContext, AtInterfaceLoc, | 
 | 426 |                                      ClassLoc, CategoryLoc, CategoryName); | 
 | 427 |     CDecl->setInvalidDecl(); | 
 | 428 |     Diag(ClassLoc, diag::err_undef_interface) << ClassName; | 
 | 429 |     return DeclPtrTy::make(CDecl); | 
 | 430 |   } | 
 | 431 |  | 
 | 432 |   if (!CategoryName) { | 
| Fariborz Jahanian | 2576061 | 2010-02-15 21:55:26 +0000 | [diff] [blame] | 433 |     // Class extensions require a special treatment. Use an existing one. | 
| Ted Kremenek | 09b6897 | 2010-02-23 19:39:46 +0000 | [diff] [blame] | 434 |     // Note that 'getClassExtension()' can return NULL. | 
| Fariborz Jahanian | 0e5ad25 | 2010-02-23 01:26:30 +0000 | [diff] [blame] | 435 |     CDecl = IDecl->getClassExtension(); | 
| Fariborz Jahanian | 24e1408 | 2010-04-02 20:53:05 +0000 | [diff] [blame] | 436 |     if (IDecl->getImplementation()) { | 
 | 437 |       Diag(ClassLoc, diag::err_class_extension_after_impl) << ClassName; | 
 | 438 |       Diag(IDecl->getImplementation()->getLocation(),  | 
 | 439 |            diag::note_implementation_declared); | 
 | 440 |     } | 
| Ted Kremenek | 09b6897 | 2010-02-23 19:39:46 +0000 | [diff] [blame] | 441 |   } | 
 | 442 |  | 
| Fariborz Jahanian | 2576061 | 2010-02-15 21:55:26 +0000 | [diff] [blame] | 443 |   if (!CDecl) { | 
| Ted Kremenek | 09b6897 | 2010-02-23 19:39:46 +0000 | [diff] [blame] | 444 |     CDecl = ObjCCategoryDecl::Create(Context, CurContext, AtInterfaceLoc, | 
 | 445 |                                      ClassLoc, CategoryLoc, CategoryName); | 
| Fariborz Jahanian | 2576061 | 2010-02-15 21:55:26 +0000 | [diff] [blame] | 446 |     // FIXME: PushOnScopeChains? | 
 | 447 |     CurContext->addDecl(CDecl); | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 448 |  | 
| Fariborz Jahanian | 2576061 | 2010-02-15 21:55:26 +0000 | [diff] [blame] | 449 |     CDecl->setClassInterface(IDecl); | 
 | 450 |     // Insert first use of class extension to the list of class's categories. | 
 | 451 |     if (!CategoryName) | 
 | 452 |       CDecl->insertNextClassCategory(); | 
 | 453 |   } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 454 |  | 
| Chris Lattner | 16b34b4 | 2009-02-16 21:30:01 +0000 | [diff] [blame] | 455 |   // If the interface is deprecated, warn about it. | 
| Douglas Gregor | 48f3bb9 | 2009-02-18 21:56:37 +0000 | [diff] [blame] | 456 |   (void)DiagnoseUseOfDecl(IDecl, ClassLoc); | 
| Chris Lattner | 70f1954 | 2009-02-16 21:26:43 +0000 | [diff] [blame] | 457 |  | 
| Fariborz Jahanian | 2576061 | 2010-02-15 21:55:26 +0000 | [diff] [blame] | 458 |   if (CategoryName) { | 
 | 459 |     /// Check for duplicate interface declaration for this category | 
 | 460 |     ObjCCategoryDecl *CDeclChain; | 
 | 461 |     for (CDeclChain = IDecl->getCategoryList(); CDeclChain; | 
 | 462 |          CDeclChain = CDeclChain->getNextClassCategory()) { | 
 | 463 |       if (CDeclChain->getIdentifier() == CategoryName) { | 
 | 464 |         // Class extensions can be declared multiple times. | 
 | 465 |         Diag(CategoryLoc, diag::warn_dup_category_def) | 
 | 466 |           << ClassName << CategoryName; | 
 | 467 |         Diag(CDeclChain->getLocation(), diag::note_previous_definition); | 
 | 468 |         break; | 
 | 469 |       } | 
| Chris Lattner | 70f1954 | 2009-02-16 21:26:43 +0000 | [diff] [blame] | 470 |     } | 
| Fariborz Jahanian | 2576061 | 2010-02-15 21:55:26 +0000 | [diff] [blame] | 471 |     if (!CDeclChain) | 
 | 472 |       CDecl->insertNextClassCategory(); | 
| Chris Lattner | 70f1954 | 2009-02-16 21:26:43 +0000 | [diff] [blame] | 473 |   } | 
| Chris Lattner | 70f1954 | 2009-02-16 21:26:43 +0000 | [diff] [blame] | 474 |  | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 475 |   if (NumProtoRefs) { | 
| Fariborz Jahanian | b106fc6 | 2009-10-05 21:32:49 +0000 | [diff] [blame] | 476 |     CDecl->setProtocolList((ObjCProtocolDecl**)ProtoRefs, NumProtoRefs,  | 
| Douglas Gregor | 18df52b | 2010-01-16 15:02:53 +0000 | [diff] [blame] | 477 |                            ProtoLocs, Context); | 
| Fariborz Jahanian | 339798e | 2009-10-05 20:41:32 +0000 | [diff] [blame] | 478 |     // Protocols in the class extension belong to the class. | 
| Fariborz Jahanian | 2576061 | 2010-02-15 21:55:26 +0000 | [diff] [blame] | 479 |     if (CDecl->IsClassExtension()) | 
| Fariborz Jahanian | 339798e | 2009-10-05 20:41:32 +0000 | [diff] [blame] | 480 |      IDecl->mergeClassExtensionProtocolList((ObjCProtocolDecl**)ProtoRefs,  | 
| Douglas Gregor | 18df52b | 2010-01-16 15:02:53 +0000 | [diff] [blame] | 481 |                                             NumProtoRefs, ProtoLocs, | 
 | 482 |                                             Context);  | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 483 |   } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 484 |  | 
| Anders Carlsson | 1528145 | 2008-11-04 16:57:32 +0000 | [diff] [blame] | 485 |   CheckObjCDeclScope(CDecl); | 
| Chris Lattner | b28317a | 2009-03-28 19:18:32 +0000 | [diff] [blame] | 486 |   return DeclPtrTy::make(CDecl); | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 487 | } | 
 | 488 |  | 
 | 489 | /// ActOnStartCategoryImplementation - Perform semantic checks on the | 
| Ted Kremenek | a526c5c | 2008-01-07 19:49:32 +0000 | [diff] [blame] | 490 | /// category implementation declaration and build an ObjCCategoryImplDecl | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 491 | /// object. | 
| Chris Lattner | b28317a | 2009-03-28 19:18:32 +0000 | [diff] [blame] | 492 | Sema::DeclPtrTy Sema::ActOnStartCategoryImplementation( | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 493 |                       SourceLocation AtCatImplLoc, | 
 | 494 |                       IdentifierInfo *ClassName, SourceLocation ClassLoc, | 
 | 495 |                       IdentifierInfo *CatName, SourceLocation CatLoc) { | 
| Douglas Gregor | c83c687 | 2010-04-15 22:33:43 +0000 | [diff] [blame] | 496 |   ObjCInterfaceDecl *IDecl = getObjCInterfaceDecl(ClassName, ClassLoc, true); | 
| Argyrios Kyrtzidis | 8a1d722 | 2009-07-21 00:05:53 +0000 | [diff] [blame] | 497 |   ObjCCategoryDecl *CatIDecl = 0; | 
 | 498 |   if (IDecl) { | 
 | 499 |     CatIDecl = IDecl->FindCategoryDeclaration(CatName); | 
 | 500 |     if (!CatIDecl) { | 
 | 501 |       // Category @implementation with no corresponding @interface. | 
 | 502 |       // Create and install one. | 
 | 503 |       CatIDecl = ObjCCategoryDecl::Create(Context, CurContext, SourceLocation(), | 
| Douglas Gregor | 3db211b | 2010-01-16 16:38:58 +0000 | [diff] [blame] | 504 |                                           SourceLocation(), SourceLocation(), | 
| Argyrios Kyrtzidis | 8a1d722 | 2009-07-21 00:05:53 +0000 | [diff] [blame] | 505 |                                           CatName); | 
 | 506 |       CatIDecl->setClassInterface(IDecl); | 
 | 507 |       CatIDecl->insertNextClassCategory(); | 
 | 508 |     } | 
 | 509 |   } | 
 | 510 |  | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 511 |   ObjCCategoryImplDecl *CDecl = | 
| Douglas Gregor | d043410 | 2009-01-09 00:49:46 +0000 | [diff] [blame] | 512 |     ObjCCategoryImplDecl::Create(Context, CurContext, AtCatImplLoc, CatName, | 
 | 513 |                                  IDecl); | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 514 |   /// Check that class of this category is already completely declared. | 
 | 515 |   if (!IDecl || IDecl->isForwardDecl()) | 
| Chris Lattner | 3c73c41 | 2008-11-19 08:23:25 +0000 | [diff] [blame] | 516 |     Diag(ClassLoc, diag::err_undef_interface) << ClassName; | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 517 |  | 
| Douglas Gregor | d043410 | 2009-01-09 00:49:46 +0000 | [diff] [blame] | 518 |   // FIXME: PushOnScopeChains? | 
| Argyrios Kyrtzidis | 17945a0 | 2009-06-30 02:36:12 +0000 | [diff] [blame] | 519 |   CurContext->addDecl(CDecl); | 
| Douglas Gregor | d043410 | 2009-01-09 00:49:46 +0000 | [diff] [blame] | 520 |  | 
| Argyrios Kyrtzidis | 8a1d722 | 2009-07-21 00:05:53 +0000 | [diff] [blame] | 521 |   /// Check that CatName, category name, is not used in another implementation. | 
 | 522 |   if (CatIDecl) { | 
 | 523 |     if (CatIDecl->getImplementation()) { | 
 | 524 |       Diag(ClassLoc, diag::err_dup_implementation_category) << ClassName | 
 | 525 |         << CatName; | 
 | 526 |       Diag(CatIDecl->getImplementation()->getLocation(), | 
 | 527 |            diag::note_previous_definition); | 
 | 528 |     } else | 
 | 529 |       CatIDecl->setImplementation(CDecl); | 
 | 530 |   } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 531 |  | 
| Anders Carlsson | 1528145 | 2008-11-04 16:57:32 +0000 | [diff] [blame] | 532 |   CheckObjCDeclScope(CDecl); | 
| Chris Lattner | b28317a | 2009-03-28 19:18:32 +0000 | [diff] [blame] | 533 |   return DeclPtrTy::make(CDecl); | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 534 | } | 
 | 535 |  | 
| Chris Lattner | b28317a | 2009-03-28 19:18:32 +0000 | [diff] [blame] | 536 | Sema::DeclPtrTy Sema::ActOnStartClassImplementation( | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 537 |                       SourceLocation AtClassImplLoc, | 
 | 538 |                       IdentifierInfo *ClassName, SourceLocation ClassLoc, | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 539 |                       IdentifierInfo *SuperClassname, | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 540 |                       SourceLocation SuperClassLoc) { | 
| Ted Kremenek | a526c5c | 2008-01-07 19:49:32 +0000 | [diff] [blame] | 541 |   ObjCInterfaceDecl* IDecl = 0; | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 542 |   // Check for another declaration kind with the same name. | 
| John McCall | f36e02d | 2009-10-09 21:13:30 +0000 | [diff] [blame] | 543 |   NamedDecl *PrevDecl | 
| Douglas Gregor | c0b3964 | 2010-04-15 23:40:53 +0000 | [diff] [blame] | 544 |     = LookupSingleName(TUScope, ClassName, ClassLoc, LookupOrdinaryName, | 
 | 545 |                        ForRedeclaration); | 
| Ted Kremenek | a526c5c | 2008-01-07 19:49:32 +0000 | [diff] [blame] | 546 |   if (PrevDecl && !isa<ObjCInterfaceDecl>(PrevDecl)) { | 
| Chris Lattner | 3c73c41 | 2008-11-19 08:23:25 +0000 | [diff] [blame] | 547 |     Diag(ClassLoc, diag::err_redefinition_different_kind) << ClassName; | 
| Chris Lattner | 5f4a682 | 2008-11-23 23:12:31 +0000 | [diff] [blame] | 548 |     Diag(PrevDecl->getLocation(), diag::note_previous_definition); | 
| Douglas Gregor | 95ff742 | 2010-01-04 17:27:12 +0000 | [diff] [blame] | 549 |   } else if ((IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl))) { | 
 | 550 |     // If this is a forward declaration of an interface, warn. | 
 | 551 |     if (IDecl->isForwardDecl()) { | 
| Chris Lattner | 3c73c41 | 2008-11-19 08:23:25 +0000 | [diff] [blame] | 552 |       Diag(ClassLoc, diag::warn_undef_interface) << ClassName; | 
| Fariborz Jahanian | 77a6be4 | 2009-04-23 21:49:04 +0000 | [diff] [blame] | 553 |       IDecl = 0; | 
 | 554 |     } | 
| Douglas Gregor | 95ff742 | 2010-01-04 17:27:12 +0000 | [diff] [blame] | 555 |   } else { | 
 | 556 |     // We did not find anything with the name ClassName; try to correct for  | 
 | 557 |     // typos in the class name. | 
 | 558 |     LookupResult R(*this, ClassName, ClassLoc, LookupOrdinaryName); | 
| Douglas Gregor | aaf8716 | 2010-04-14 20:04:41 +0000 | [diff] [blame] | 559 |     if (CorrectTypo(R, TUScope, 0, 0, false, CTC_NoKeywords) && | 
| Douglas Gregor | 95ff742 | 2010-01-04 17:27:12 +0000 | [diff] [blame] | 560 |         (IDecl = R.getAsSingle<ObjCInterfaceDecl>())) { | 
| Douglas Gregor | a6f2638 | 2010-01-06 23:44:25 +0000 | [diff] [blame] | 561 |       // Suggest the (potentially) correct interface name. However, put the | 
 | 562 |       // fix-it hint itself in a separate note, since changing the name in  | 
 | 563 |       // the warning would make the fix-it change semantics.However, don't | 
| Douglas Gregor | 95ff742 | 2010-01-04 17:27:12 +0000 | [diff] [blame] | 564 |       // provide a code-modification hint or use the typo name for recovery, | 
 | 565 |       // because this is just a warning. The program may actually be correct. | 
 | 566 |       Diag(ClassLoc, diag::warn_undef_interface_suggest) | 
 | 567 |         << ClassName << R.getLookupName(); | 
| Douglas Gregor | a6f2638 | 2010-01-06 23:44:25 +0000 | [diff] [blame] | 568 |       Diag(IDecl->getLocation(), diag::note_previous_decl) | 
 | 569 |         << R.getLookupName() | 
| Douglas Gregor | 849b243 | 2010-03-31 17:46:05 +0000 | [diff] [blame] | 570 |         << FixItHint::CreateReplacement(ClassLoc, | 
 | 571 |                                         R.getLookupName().getAsString()); | 
| Douglas Gregor | 95ff742 | 2010-01-04 17:27:12 +0000 | [diff] [blame] | 572 |       IDecl = 0; | 
 | 573 |     } else { | 
 | 574 |       Diag(ClassLoc, diag::warn_undef_interface) << ClassName; | 
 | 575 |     } | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 576 |   } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 577 |  | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 578 |   // Check that super class name is valid class name | 
| Ted Kremenek | a526c5c | 2008-01-07 19:49:32 +0000 | [diff] [blame] | 579 |   ObjCInterfaceDecl* SDecl = 0; | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 580 |   if (SuperClassname) { | 
 | 581 |     // Check if a different kind of symbol declared in this scope. | 
| Douglas Gregor | c83c687 | 2010-04-15 22:33:43 +0000 | [diff] [blame] | 582 |     PrevDecl = LookupSingleName(TUScope, SuperClassname, SuperClassLoc, | 
 | 583 |                                 LookupOrdinaryName); | 
| Ted Kremenek | a526c5c | 2008-01-07 19:49:32 +0000 | [diff] [blame] | 584 |     if (PrevDecl && !isa<ObjCInterfaceDecl>(PrevDecl)) { | 
| Chris Lattner | 3c73c41 | 2008-11-19 08:23:25 +0000 | [diff] [blame] | 585 |       Diag(SuperClassLoc, diag::err_redefinition_different_kind) | 
 | 586 |         << SuperClassname; | 
| Chris Lattner | 5f4a682 | 2008-11-23 23:12:31 +0000 | [diff] [blame] | 587 |       Diag(PrevDecl->getLocation(), diag::note_previous_definition); | 
| Chris Lattner | 3c73c41 | 2008-11-19 08:23:25 +0000 | [diff] [blame] | 588 |     } else { | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 589 |       SDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl); | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 590 |       if (!SDecl) | 
| Chris Lattner | 3c73c41 | 2008-11-19 08:23:25 +0000 | [diff] [blame] | 591 |         Diag(SuperClassLoc, diag::err_undef_superclass) | 
 | 592 |           << SuperClassname << ClassName; | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 593 |       else if (IDecl && IDecl->getSuperClass() != SDecl) { | 
 | 594 |         // This implementation and its interface do not have the same | 
 | 595 |         // super class. | 
| Chris Lattner | 3c73c41 | 2008-11-19 08:23:25 +0000 | [diff] [blame] | 596 |         Diag(SuperClassLoc, diag::err_conflicting_super_class) | 
| Chris Lattner | 08631c5 | 2008-11-23 21:45:46 +0000 | [diff] [blame] | 597 |           << SDecl->getDeclName(); | 
| Chris Lattner | 5f4a682 | 2008-11-23 23:12:31 +0000 | [diff] [blame] | 598 |         Diag(SDecl->getLocation(), diag::note_previous_definition); | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 599 |       } | 
 | 600 |     } | 
 | 601 |   } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 602 |  | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 603 |   if (!IDecl) { | 
 | 604 |     // Legacy case of @implementation with no corresponding @interface. | 
 | 605 |     // Build, chain & install the interface decl into the identifier. | 
| Daniel Dunbar | f641492 | 2008-08-20 18:02:42 +0000 | [diff] [blame] | 606 |  | 
| Mike Stump | 390b4cc | 2009-05-16 07:39:55 +0000 | [diff] [blame] | 607 |     // FIXME: Do we support attributes on the @implementation? If so we should | 
 | 608 |     // copy them over. | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 609 |     IDecl = ObjCInterfaceDecl::Create(Context, CurContext, AtClassImplLoc, | 
| Douglas Gregor | d043410 | 2009-01-09 00:49:46 +0000 | [diff] [blame] | 610 |                                       ClassName, ClassLoc, false, true); | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 611 |     IDecl->setSuperClass(SDecl); | 
 | 612 |     IDecl->setLocEnd(ClassLoc); | 
| Douglas Gregor | 8b9fb30 | 2009-04-24 00:16:12 +0000 | [diff] [blame] | 613 |  | 
 | 614 |     PushOnScopeChains(IDecl, TUScope); | 
| Daniel Dunbar | 24c8991 | 2009-04-21 21:41:56 +0000 | [diff] [blame] | 615 |   } else { | 
 | 616 |     // Mark the interface as being completed, even if it was just as | 
 | 617 |     //   @class ....; | 
 | 618 |     // declaration; the user cannot reopen it. | 
 | 619 |     IDecl->setForwardDecl(false); | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 620 |   } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 621 |  | 
 | 622 |   ObjCImplementationDecl* IMPDecl = | 
 | 623 |     ObjCImplementationDecl::Create(Context, CurContext, AtClassImplLoc, | 
| Douglas Gregor | 4afa39d | 2009-01-20 01:17:11 +0000 | [diff] [blame] | 624 |                                    IDecl, SDecl); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 625 |  | 
| Anders Carlsson | 1528145 | 2008-11-04 16:57:32 +0000 | [diff] [blame] | 626 |   if (CheckObjCDeclScope(IMPDecl)) | 
| Chris Lattner | b28317a | 2009-03-28 19:18:32 +0000 | [diff] [blame] | 627 |     return DeclPtrTy::make(IMPDecl); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 628 |  | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 629 |   // Check that there is no duplicate implementation of this class. | 
| Argyrios Kyrtzidis | 8701877 | 2009-07-21 00:06:04 +0000 | [diff] [blame] | 630 |   if (IDecl->getImplementation()) { | 
| Chris Lattner | 75c9cae | 2008-03-16 20:53:07 +0000 | [diff] [blame] | 631 |     // FIXME: Don't leak everything! | 
| Chris Lattner | 3c73c41 | 2008-11-19 08:23:25 +0000 | [diff] [blame] | 632 |     Diag(ClassLoc, diag::err_dup_implementation_class) << ClassName; | 
| Argyrios Kyrtzidis | 8701877 | 2009-07-21 00:06:04 +0000 | [diff] [blame] | 633 |     Diag(IDecl->getImplementation()->getLocation(), | 
 | 634 |          diag::note_previous_definition); | 
 | 635 |   } else { // add it to the list. | 
| Argyrios Kyrtzidis | 8a1d722 | 2009-07-21 00:05:53 +0000 | [diff] [blame] | 636 |     IDecl->setImplementation(IMPDecl); | 
| Douglas Gregor | 8fc463a | 2009-04-24 00:11:27 +0000 | [diff] [blame] | 637 |     PushOnScopeChains(IMPDecl, TUScope); | 
| Argyrios Kyrtzidis | 8a1d722 | 2009-07-21 00:05:53 +0000 | [diff] [blame] | 638 |   } | 
| Chris Lattner | b28317a | 2009-03-28 19:18:32 +0000 | [diff] [blame] | 639 |   return DeclPtrTy::make(IMPDecl); | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 640 | } | 
 | 641 |  | 
| Ted Kremenek | a526c5c | 2008-01-07 19:49:32 +0000 | [diff] [blame] | 642 | void Sema::CheckImplementationIvars(ObjCImplementationDecl *ImpDecl, | 
 | 643 |                                     ObjCIvarDecl **ivars, unsigned numIvars, | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 644 |                                     SourceLocation RBrace) { | 
 | 645 |   assert(ImpDecl && "missing implementation decl"); | 
| Douglas Gregor | 4afa39d | 2009-01-20 01:17:11 +0000 | [diff] [blame] | 646 |   ObjCInterfaceDecl* IDecl = ImpDecl->getClassInterface(); | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 647 |   if (!IDecl) | 
 | 648 |     return; | 
 | 649 |   /// Check case of non-existing @interface decl. | 
 | 650 |   /// (legacy objective-c @implementation decl without an @interface decl). | 
 | 651 |   /// Add implementations's ivar to the synthesize class's ivar list. | 
| Steve Naroff | 33feeb0 | 2009-04-20 20:09:33 +0000 | [diff] [blame] | 652 |   if (IDecl->isImplicitInterfaceDecl()) { | 
| Chris Lattner | 38af2de | 2009-02-20 21:35:13 +0000 | [diff] [blame] | 653 |     IDecl->setLocEnd(RBrace); | 
| Fariborz Jahanian | 3a21cd9 | 2010-02-17 17:00:07 +0000 | [diff] [blame] | 654 |     // Add ivar's to class's DeclContext. | 
 | 655 |     for (unsigned i = 0, e = numIvars; i != e; ++i) { | 
| Fariborz Jahanian | 2f14c4d | 2010-02-17 18:10:54 +0000 | [diff] [blame] | 656 |       ivars[i]->setLexicalDeclContext(ImpDecl); | 
 | 657 |       IDecl->makeDeclVisibleInContext(ivars[i], false); | 
| Fariborz Jahanian | 11062e1 | 2010-02-19 00:31:17 +0000 | [diff] [blame] | 658 |       ImpDecl->addDecl(ivars[i]); | 
| Fariborz Jahanian | 3a21cd9 | 2010-02-17 17:00:07 +0000 | [diff] [blame] | 659 |     } | 
 | 660 |      | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 661 |     return; | 
 | 662 |   } | 
 | 663 |   // If implementation has empty ivar list, just return. | 
 | 664 |   if (numIvars == 0) | 
 | 665 |     return; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 666 |  | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 667 |   assert(ivars && "missing @implementation ivars"); | 
| Fariborz Jahanian | bd94d44 | 2010-02-19 20:58:54 +0000 | [diff] [blame] | 668 |   if (LangOpts.ObjCNonFragileABI2) { | 
 | 669 |     if (ImpDecl->getSuperClass()) | 
 | 670 |       Diag(ImpDecl->getLocation(), diag::warn_on_superclass_use); | 
 | 671 |     for (unsigned i = 0; i < numIvars; i++) { | 
 | 672 |       ObjCIvarDecl* ImplIvar = ivars[i]; | 
 | 673 |       if (const ObjCIvarDecl *ClsIvar =  | 
 | 674 |             IDecl->getIvarDecl(ImplIvar->getIdentifier())) { | 
 | 675 |         Diag(ImplIvar->getLocation(), diag::err_duplicate_ivar_declaration);  | 
 | 676 |         Diag(ClsIvar->getLocation(), diag::note_previous_definition); | 
 | 677 |         continue; | 
 | 678 |       } | 
| Fariborz Jahanian | bd94d44 | 2010-02-19 20:58:54 +0000 | [diff] [blame] | 679 |       // Instance ivar to Implementation's DeclContext. | 
 | 680 |       ImplIvar->setLexicalDeclContext(ImpDecl); | 
 | 681 |       IDecl->makeDeclVisibleInContext(ImplIvar, false); | 
 | 682 |       ImpDecl->addDecl(ImplIvar); | 
 | 683 |     } | 
 | 684 |     return; | 
 | 685 |   } | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 686 |   // Check interface's Ivar list against those in the implementation. | 
 | 687 |   // names and types must match. | 
 | 688 |   // | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 689 |   unsigned j = 0; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 690 |   ObjCInterfaceDecl::ivar_iterator | 
| Chris Lattner | 4c52509 | 2007-12-12 17:58:05 +0000 | [diff] [blame] | 691 |     IVI = IDecl->ivar_begin(), IVE = IDecl->ivar_end(); | 
 | 692 |   for (; numIvars > 0 && IVI != IVE; ++IVI) { | 
| Ted Kremenek | a526c5c | 2008-01-07 19:49:32 +0000 | [diff] [blame] | 693 |     ObjCIvarDecl* ImplIvar = ivars[j++]; | 
 | 694 |     ObjCIvarDecl* ClsIvar = *IVI; | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 695 |     assert (ImplIvar && "missing implementation ivar"); | 
 | 696 |     assert (ClsIvar && "missing class ivar"); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 697 |  | 
| Steve Naroff | ca33129 | 2009-03-03 14:49:36 +0000 | [diff] [blame] | 698 |     // First, make sure the types match. | 
| Chris Lattner | 1b63eef | 2008-07-27 00:05:05 +0000 | [diff] [blame] | 699 |     if (Context.getCanonicalType(ImplIvar->getType()) != | 
 | 700 |         Context.getCanonicalType(ClsIvar->getType())) { | 
| Chris Lattner | fa25bbb | 2008-11-19 05:08:23 +0000 | [diff] [blame] | 701 |       Diag(ImplIvar->getLocation(), diag::err_conflicting_ivar_type) | 
| Chris Lattner | 08631c5 | 2008-11-23 21:45:46 +0000 | [diff] [blame] | 702 |         << ImplIvar->getIdentifier() | 
 | 703 |         << ImplIvar->getType() << ClsIvar->getType(); | 
| Chris Lattner | 5f4a682 | 2008-11-23 23:12:31 +0000 | [diff] [blame] | 704 |       Diag(ClsIvar->getLocation(), diag::note_previous_definition); | 
| Steve Naroff | ca33129 | 2009-03-03 14:49:36 +0000 | [diff] [blame] | 705 |     } else if (ImplIvar->isBitField() && ClsIvar->isBitField()) { | 
 | 706 |       Expr *ImplBitWidth = ImplIvar->getBitWidth(); | 
 | 707 |       Expr *ClsBitWidth = ClsIvar->getBitWidth(); | 
| Eli Friedman | 9a901bb | 2009-04-26 19:19:15 +0000 | [diff] [blame] | 708 |       if (ImplBitWidth->EvaluateAsInt(Context).getZExtValue() != | 
 | 709 |           ClsBitWidth->EvaluateAsInt(Context).getZExtValue()) { | 
| Steve Naroff | ca33129 | 2009-03-03 14:49:36 +0000 | [diff] [blame] | 710 |         Diag(ImplBitWidth->getLocStart(), diag::err_conflicting_ivar_bitwidth) | 
 | 711 |           << ImplIvar->getIdentifier(); | 
 | 712 |         Diag(ClsBitWidth->getLocStart(), diag::note_previous_definition); | 
 | 713 |       } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 714 |     } | 
| Steve Naroff | ca33129 | 2009-03-03 14:49:36 +0000 | [diff] [blame] | 715 |     // Make sure the names are identical. | 
 | 716 |     if (ImplIvar->getIdentifier() != ClsIvar->getIdentifier()) { | 
| Chris Lattner | fa25bbb | 2008-11-19 05:08:23 +0000 | [diff] [blame] | 717 |       Diag(ImplIvar->getLocation(), diag::err_conflicting_ivar_name) | 
| Chris Lattner | 08631c5 | 2008-11-23 21:45:46 +0000 | [diff] [blame] | 718 |         << ImplIvar->getIdentifier() << ClsIvar->getIdentifier(); | 
| Chris Lattner | 5f4a682 | 2008-11-23 23:12:31 +0000 | [diff] [blame] | 719 |       Diag(ClsIvar->getLocation(), diag::note_previous_definition); | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 720 |     } | 
 | 721 |     --numIvars; | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 722 |   } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 723 |  | 
| Chris Lattner | 609e4c7 | 2007-12-12 18:11:49 +0000 | [diff] [blame] | 724 |   if (numIvars > 0) | 
| Chris Lattner | 0e39105 | 2007-12-12 18:19:52 +0000 | [diff] [blame] | 725 |     Diag(ivars[j]->getLocation(), diag::err_inconsistant_ivar_count); | 
| Chris Lattner | 609e4c7 | 2007-12-12 18:11:49 +0000 | [diff] [blame] | 726 |   else if (IVI != IVE) | 
| Chris Lattner | 0e39105 | 2007-12-12 18:19:52 +0000 | [diff] [blame] | 727 |     Diag((*IVI)->getLocation(), diag::err_inconsistant_ivar_count); | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 728 | } | 
 | 729 |  | 
| Steve Naroff | 3c2eb66 | 2008-02-10 21:38:56 +0000 | [diff] [blame] | 730 | void Sema::WarnUndefinedMethod(SourceLocation ImpLoc, ObjCMethodDecl *method, | 
| Fariborz Jahanian | 5214683 | 2010-03-31 18:23:33 +0000 | [diff] [blame] | 731 |                                bool &IncompleteImpl, unsigned DiagID) { | 
| Steve Naroff | 3c2eb66 | 2008-02-10 21:38:56 +0000 | [diff] [blame] | 732 |   if (!IncompleteImpl) { | 
 | 733 |     Diag(ImpLoc, diag::warn_incomplete_impl); | 
 | 734 |     IncompleteImpl = true; | 
 | 735 |   } | 
| Fariborz Jahanian | 5214683 | 2010-03-31 18:23:33 +0000 | [diff] [blame] | 736 |   Diag(method->getLocation(), DiagID)  | 
| Fariborz Jahanian | 8822f7c | 2010-03-27 19:02:17 +0000 | [diff] [blame] | 737 |     << method->getDeclName(); | 
| Steve Naroff | 3c2eb66 | 2008-02-10 21:38:56 +0000 | [diff] [blame] | 738 | } | 
 | 739 |  | 
| Fariborz Jahanian | 8daab97 | 2008-12-05 18:18:52 +0000 | [diff] [blame] | 740 | void Sema::WarnConflictingTypedMethods(ObjCMethodDecl *ImpMethodDecl, | 
 | 741 |                                        ObjCMethodDecl *IntfMethodDecl) { | 
| Chris Lattner | 5272b7f | 2009-04-11 18:01:59 +0000 | [diff] [blame] | 742 |   if (!Context.typesAreCompatible(IntfMethodDecl->getResultType(), | 
| Fariborz Jahanian | 2574a68 | 2009-05-14 23:52:54 +0000 | [diff] [blame] | 743 |                                   ImpMethodDecl->getResultType()) && | 
| Steve Naroff | 4084c30 | 2009-07-23 01:01:38 +0000 | [diff] [blame] | 744 |       !Context.QualifiedIdConformsQualifiedId(IntfMethodDecl->getResultType(), | 
 | 745 |                                               ImpMethodDecl->getResultType())) { | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 746 |     Diag(ImpMethodDecl->getLocation(), diag::warn_conflicting_ret_types) | 
| Chris Lattner | 3aff919 | 2009-04-11 19:58:42 +0000 | [diff] [blame] | 747 |       << ImpMethodDecl->getDeclName() << IntfMethodDecl->getResultType() | 
 | 748 |       << ImpMethodDecl->getResultType(); | 
| Fariborz Jahanian | 8daab97 | 2008-12-05 18:18:52 +0000 | [diff] [blame] | 749 |     Diag(IntfMethodDecl->getLocation(), diag::note_previous_definition); | 
 | 750 |   } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 751 |  | 
| Chris Lattner | 3aff919 | 2009-04-11 19:58:42 +0000 | [diff] [blame] | 752 |   for (ObjCMethodDecl::param_iterator IM = ImpMethodDecl->param_begin(), | 
 | 753 |        IF = IntfMethodDecl->param_begin(), EM = ImpMethodDecl->param_end(); | 
 | 754 |        IM != EM; ++IM, ++IF) { | 
| Fariborz Jahanian | 3393f81 | 2009-11-18 18:56:09 +0000 | [diff] [blame] | 755 |     QualType ParmDeclTy = (*IF)->getType().getUnqualifiedType(); | 
 | 756 |     QualType ParmImpTy = (*IM)->getType().getUnqualifiedType(); | 
 | 757 |     if (Context.typesAreCompatible(ParmDeclTy, ParmImpTy) || | 
 | 758 |         Context.QualifiedIdConformsQualifiedId(ParmDeclTy, ParmImpTy)) | 
| Chris Lattner | 3aff919 | 2009-04-11 19:58:42 +0000 | [diff] [blame] | 759 |       continue; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 760 |  | 
 | 761 |     Diag((*IM)->getLocation(), diag::warn_conflicting_param_types) | 
| Chris Lattner | 3aff919 | 2009-04-11 19:58:42 +0000 | [diff] [blame] | 762 |       << ImpMethodDecl->getDeclName() << (*IF)->getType() | 
 | 763 |       << (*IM)->getType(); | 
| Chris Lattner | d1e0f5a | 2009-04-11 20:14:49 +0000 | [diff] [blame] | 764 |     Diag((*IF)->getLocation(), diag::note_previous_definition); | 
| Chris Lattner | 3aff919 | 2009-04-11 19:58:42 +0000 | [diff] [blame] | 765 |   } | 
| Fariborz Jahanian | 561da7e | 2010-05-21 23:28:58 +0000 | [diff] [blame] | 766 |   if (ImpMethodDecl->isVariadic() != IntfMethodDecl->isVariadic()) { | 
 | 767 |     Diag(ImpMethodDecl->getLocation(), diag::warn_conflicting_variadic); | 
 | 768 |     Diag(IntfMethodDecl->getLocation(), diag::note_previous_declaration); | 
 | 769 |   } | 
| Fariborz Jahanian | 8daab97 | 2008-12-05 18:18:52 +0000 | [diff] [blame] | 770 | } | 
 | 771 |  | 
| Mike Stump | 390b4cc | 2009-05-16 07:39:55 +0000 | [diff] [blame] | 772 | /// FIXME: Type hierarchies in Objective-C can be deep. We could most likely | 
 | 773 | /// improve the efficiency of selector lookups and type checking by associating | 
 | 774 | /// with each protocol / interface / category the flattened instance tables. If | 
 | 775 | /// we used an immutable set to keep the table then it wouldn't add significant | 
 | 776 | /// memory cost and it would be handy for lookups. | 
| Daniel Dunbar | b20ef3e | 2008-08-27 05:40:03 +0000 | [diff] [blame] | 777 |  | 
| Steve Naroff | efe7f36 | 2008-02-08 22:06:17 +0000 | [diff] [blame] | 778 | /// CheckProtocolMethodDefs - This routine checks unimplemented methods | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 779 | /// Declared in protocol, and those referenced by it. | 
| Steve Naroff | efe7f36 | 2008-02-08 22:06:17 +0000 | [diff] [blame] | 780 | void Sema::CheckProtocolMethodDefs(SourceLocation ImpLoc, | 
 | 781 |                                    ObjCProtocolDecl *PDecl, | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 782 |                                    bool& IncompleteImpl, | 
| Steve Naroff | efe7f36 | 2008-02-08 22:06:17 +0000 | [diff] [blame] | 783 |                                    const llvm::DenseSet<Selector> &InsMap, | 
| Daniel Dunbar | 7ad1b1f | 2008-09-04 20:01:15 +0000 | [diff] [blame] | 784 |                                    const llvm::DenseSet<Selector> &ClsMap, | 
| Fariborz Jahanian | f283859 | 2010-03-27 21:10:05 +0000 | [diff] [blame] | 785 |                                    ObjCContainerDecl *CDecl) { | 
 | 786 |   ObjCInterfaceDecl *IDecl; | 
 | 787 |   if (ObjCCategoryDecl *C = dyn_cast<ObjCCategoryDecl>(CDecl)) | 
 | 788 |     IDecl = C->getClassInterface(); | 
 | 789 |   else | 
 | 790 |     IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl); | 
 | 791 |   assert (IDecl && "CheckProtocolMethodDefs - IDecl is null"); | 
 | 792 |    | 
| Daniel Dunbar | 7ad1b1f | 2008-09-04 20:01:15 +0000 | [diff] [blame] | 793 |   ObjCInterfaceDecl *Super = IDecl->getSuperClass(); | 
| Fariborz Jahanian | cd18762 | 2009-05-22 17:12:32 +0000 | [diff] [blame] | 794 |   ObjCInterfaceDecl *NSIDecl = 0; | 
 | 795 |   if (getLangOptions().NeXTRuntime) { | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 796 |     // check to see if class implements forwardInvocation method and objects | 
 | 797 |     // of this class are derived from 'NSProxy' so that to forward requests | 
| Fariborz Jahanian | cd18762 | 2009-05-22 17:12:32 +0000 | [diff] [blame] | 798 |     // from one object to another. | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 799 |     // Under such conditions, which means that every method possible is | 
 | 800 |     // implemented in the class, we should not issue "Method definition not | 
| Fariborz Jahanian | cd18762 | 2009-05-22 17:12:32 +0000 | [diff] [blame] | 801 |     // found" warnings. | 
 | 802 |     // FIXME: Use a general GetUnarySelector method for this. | 
 | 803 |     IdentifierInfo* II = &Context.Idents.get("forwardInvocation"); | 
 | 804 |     Selector fISelector = Context.Selectors.getSelector(1, &II); | 
 | 805 |     if (InsMap.count(fISelector)) | 
 | 806 |       // Is IDecl derived from 'NSProxy'? If so, no instance methods | 
 | 807 |       // need be implemented in the implementation. | 
 | 808 |       NSIDecl = IDecl->lookupInheritedClass(&Context.Idents.get("NSProxy")); | 
 | 809 |   } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 810 |  | 
| Daniel Dunbar | 7ad1b1f | 2008-09-04 20:01:15 +0000 | [diff] [blame] | 811 |   // If a method lookup fails locally we still need to look and see if | 
 | 812 |   // the method was implemented by a base class or an inherited | 
 | 813 |   // protocol. This lookup is slow, but occurs rarely in correct code | 
 | 814 |   // and otherwise would terminate in a warning. | 
 | 815 |  | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 816 |   // check unimplemented instance methods. | 
| Fariborz Jahanian | cd18762 | 2009-05-22 17:12:32 +0000 | [diff] [blame] | 817 |   if (!NSIDecl) | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 818 |     for (ObjCProtocolDecl::instmeth_iterator I = PDecl->instmeth_begin(), | 
| Argyrios Kyrtzidis | 17945a0 | 2009-06-30 02:36:12 +0000 | [diff] [blame] | 819 |          E = PDecl->instmeth_end(); I != E; ++I) { | 
| Fariborz Jahanian | cd18762 | 2009-05-22 17:12:32 +0000 | [diff] [blame] | 820 |       ObjCMethodDecl *method = *I; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 821 |       if (method->getImplementationControl() != ObjCMethodDecl::Optional && | 
| Fariborz Jahanian | cd18762 | 2009-05-22 17:12:32 +0000 | [diff] [blame] | 822 |           !method->isSynthesized() && !InsMap.count(method->getSelector()) && | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 823 |           (!Super || | 
| Argyrios Kyrtzidis | 17945a0 | 2009-06-30 02:36:12 +0000 | [diff] [blame] | 824 |            !Super->lookupInstanceMethod(method->getSelector()))) { | 
| Fariborz Jahanian | cd18762 | 2009-05-22 17:12:32 +0000 | [diff] [blame] | 825 |             // Ugly, but necessary. Method declared in protcol might have | 
 | 826 |             // have been synthesized due to a property declared in the class which | 
 | 827 |             // uses the protocol. | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 828 |             ObjCMethodDecl *MethodInClass = | 
| Argyrios Kyrtzidis | 17945a0 | 2009-06-30 02:36:12 +0000 | [diff] [blame] | 829 |             IDecl->lookupInstanceMethod(method->getSelector()); | 
| Fariborz Jahanian | 8822f7c | 2010-03-27 19:02:17 +0000 | [diff] [blame] | 830 |             if (!MethodInClass || !MethodInClass->isSynthesized()) { | 
| Fariborz Jahanian | 5214683 | 2010-03-31 18:23:33 +0000 | [diff] [blame] | 831 |               unsigned DIAG = diag::warn_unimplemented_protocol_method; | 
 | 832 |               if (Diags.getDiagnosticLevel(DIAG) != Diagnostic::Ignored) { | 
 | 833 |                 WarnUndefinedMethod(ImpLoc, method, IncompleteImpl, DIAG); | 
 | 834 |                 Diag(CDecl->getLocation(), diag::note_required_for_protocol_at) | 
 | 835 |                   << PDecl->getDeclName(); | 
 | 836 |               } | 
| Fariborz Jahanian | 8822f7c | 2010-03-27 19:02:17 +0000 | [diff] [blame] | 837 |             } | 
| Fariborz Jahanian | cd18762 | 2009-05-22 17:12:32 +0000 | [diff] [blame] | 838 |           } | 
 | 839 |     } | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 840 |   // check unimplemented class methods | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 841 |   for (ObjCProtocolDecl::classmeth_iterator | 
| Argyrios Kyrtzidis | 17945a0 | 2009-06-30 02:36:12 +0000 | [diff] [blame] | 842 |          I = PDecl->classmeth_begin(), E = PDecl->classmeth_end(); | 
| Douglas Gregor | 6ab3524 | 2009-04-09 21:40:53 +0000 | [diff] [blame] | 843 |        I != E; ++I) { | 
| Ted Kremenek | a526c5c | 2008-01-07 19:49:32 +0000 | [diff] [blame] | 844 |     ObjCMethodDecl *method = *I; | 
| Daniel Dunbar | 7ad1b1f | 2008-09-04 20:01:15 +0000 | [diff] [blame] | 845 |     if (method->getImplementationControl() != ObjCMethodDecl::Optional && | 
 | 846 |         !ClsMap.count(method->getSelector()) && | 
| Fariborz Jahanian | 8822f7c | 2010-03-27 19:02:17 +0000 | [diff] [blame] | 847 |         (!Super || !Super->lookupClassMethod(method->getSelector()))) { | 
| Fariborz Jahanian | 5214683 | 2010-03-31 18:23:33 +0000 | [diff] [blame] | 848 |       unsigned DIAG = diag::warn_unimplemented_protocol_method; | 
 | 849 |       if (Diags.getDiagnosticLevel(DIAG) != Diagnostic::Ignored) { | 
 | 850 |         WarnUndefinedMethod(ImpLoc, method, IncompleteImpl, DIAG); | 
 | 851 |         Diag(IDecl->getLocation(), diag::note_required_for_protocol_at) << | 
 | 852 |           PDecl->getDeclName(); | 
 | 853 |       } | 
| Fariborz Jahanian | 8822f7c | 2010-03-27 19:02:17 +0000 | [diff] [blame] | 854 |     } | 
| Steve Naroff | 58dbdeb | 2007-12-14 23:37:57 +0000 | [diff] [blame] | 855 |   } | 
| Chris Lattner | 780f329 | 2008-07-21 21:32:27 +0000 | [diff] [blame] | 856 |   // Check on this protocols's referenced protocols, recursively. | 
 | 857 |   for (ObjCProtocolDecl::protocol_iterator PI = PDecl->protocol_begin(), | 
 | 858 |        E = PDecl->protocol_end(); PI != E; ++PI) | 
| Daniel Dunbar | 7ad1b1f | 2008-09-04 20:01:15 +0000 | [diff] [blame] | 859 |     CheckProtocolMethodDefs(ImpLoc, *PI, IncompleteImpl, InsMap, ClsMap, IDecl); | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 860 | } | 
 | 861 |  | 
| Fariborz Jahanian | b33f3ad | 2009-05-01 20:07:12 +0000 | [diff] [blame] | 862 | /// MatchAllMethodDeclarations - Check methods declaraed in interface or | 
 | 863 | /// or protocol against those declared in their implementations. | 
 | 864 | /// | 
 | 865 | void Sema::MatchAllMethodDeclarations(const llvm::DenseSet<Selector> &InsMap, | 
 | 866 |                                       const llvm::DenseSet<Selector> &ClsMap, | 
 | 867 |                                       llvm::DenseSet<Selector> &InsMapSeen, | 
 | 868 |                                       llvm::DenseSet<Selector> &ClsMapSeen, | 
 | 869 |                                       ObjCImplDecl* IMPDecl, | 
 | 870 |                                       ObjCContainerDecl* CDecl, | 
 | 871 |                                       bool &IncompleteImpl, | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 872 |                                       bool ImmediateClass) { | 
| Fariborz Jahanian | b33f3ad | 2009-05-01 20:07:12 +0000 | [diff] [blame] | 873 |   // Check and see if instance methods in class interface have been | 
 | 874 |   // implemented in the implementation class. If so, their types match. | 
| Argyrios Kyrtzidis | 17945a0 | 2009-06-30 02:36:12 +0000 | [diff] [blame] | 875 |   for (ObjCInterfaceDecl::instmeth_iterator I = CDecl->instmeth_begin(), | 
 | 876 |        E = CDecl->instmeth_end(); I != E; ++I) { | 
| Fariborz Jahanian | b33f3ad | 2009-05-01 20:07:12 +0000 | [diff] [blame] | 877 |     if (InsMapSeen.count((*I)->getSelector())) | 
 | 878 |         continue; | 
 | 879 |     InsMapSeen.insert((*I)->getSelector()); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 880 |     if (!(*I)->isSynthesized() && | 
| Fariborz Jahanian | b33f3ad | 2009-05-01 20:07:12 +0000 | [diff] [blame] | 881 |         !InsMap.count((*I)->getSelector())) { | 
 | 882 |       if (ImmediateClass) | 
| Fariborz Jahanian | 5214683 | 2010-03-31 18:23:33 +0000 | [diff] [blame] | 883 |         WarnUndefinedMethod(IMPDecl->getLocation(), *I, IncompleteImpl, | 
 | 884 |                             diag::note_undef_method_impl); | 
| Fariborz Jahanian | b33f3ad | 2009-05-01 20:07:12 +0000 | [diff] [blame] | 885 |       continue; | 
| Mike Stump | ac5fc7c | 2009-08-04 21:02:39 +0000 | [diff] [blame] | 886 |     } else { | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 887 |       ObjCMethodDecl *ImpMethodDecl = | 
| Argyrios Kyrtzidis | 17945a0 | 2009-06-30 02:36:12 +0000 | [diff] [blame] | 888 |       IMPDecl->getInstanceMethod((*I)->getSelector()); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 889 |       ObjCMethodDecl *IntfMethodDecl = | 
| Argyrios Kyrtzidis | 17945a0 | 2009-06-30 02:36:12 +0000 | [diff] [blame] | 890 |       CDecl->getInstanceMethod((*I)->getSelector()); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 891 |       assert(IntfMethodDecl && | 
| Fariborz Jahanian | b33f3ad | 2009-05-01 20:07:12 +0000 | [diff] [blame] | 892 |              "IntfMethodDecl is null in ImplMethodsVsClassMethods"); | 
 | 893 |       // ImpMethodDecl may be null as in a @dynamic property. | 
 | 894 |       if (ImpMethodDecl) | 
 | 895 |         WarnConflictingTypedMethods(ImpMethodDecl, IntfMethodDecl); | 
 | 896 |     } | 
 | 897 |   } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 898 |  | 
| Fariborz Jahanian | b33f3ad | 2009-05-01 20:07:12 +0000 | [diff] [blame] | 899 |   // Check and see if class methods in class interface have been | 
 | 900 |   // implemented in the implementation class. If so, their types match. | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 901 |    for (ObjCInterfaceDecl::classmeth_iterator | 
| Argyrios Kyrtzidis | 17945a0 | 2009-06-30 02:36:12 +0000 | [diff] [blame] | 902 |        I = CDecl->classmeth_begin(), E = CDecl->classmeth_end(); I != E; ++I) { | 
| Fariborz Jahanian | b33f3ad | 2009-05-01 20:07:12 +0000 | [diff] [blame] | 903 |      if (ClsMapSeen.count((*I)->getSelector())) | 
 | 904 |        continue; | 
 | 905 |      ClsMapSeen.insert((*I)->getSelector()); | 
 | 906 |     if (!ClsMap.count((*I)->getSelector())) { | 
 | 907 |       if (ImmediateClass) | 
| Fariborz Jahanian | 5214683 | 2010-03-31 18:23:33 +0000 | [diff] [blame] | 908 |         WarnUndefinedMethod(IMPDecl->getLocation(), *I, IncompleteImpl, | 
 | 909 |                             diag::note_undef_method_impl); | 
| Mike Stump | ac5fc7c | 2009-08-04 21:02:39 +0000 | [diff] [blame] | 910 |     } else { | 
| Argyrios Kyrtzidis | 17945a0 | 2009-06-30 02:36:12 +0000 | [diff] [blame] | 911 |       ObjCMethodDecl *ImpMethodDecl = | 
 | 912 |         IMPDecl->getClassMethod((*I)->getSelector()); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 913 |       ObjCMethodDecl *IntfMethodDecl = | 
| Argyrios Kyrtzidis | 17945a0 | 2009-06-30 02:36:12 +0000 | [diff] [blame] | 914 |         CDecl->getClassMethod((*I)->getSelector()); | 
| Fariborz Jahanian | b33f3ad | 2009-05-01 20:07:12 +0000 | [diff] [blame] | 915 |       WarnConflictingTypedMethods(ImpMethodDecl, IntfMethodDecl); | 
 | 916 |     } | 
 | 917 |   } | 
 | 918 |   if (ObjCInterfaceDecl *I = dyn_cast<ObjCInterfaceDecl> (CDecl)) { | 
 | 919 |     // Check for any implementation of a methods declared in protocol. | 
 | 920 |     for (ObjCInterfaceDecl::protocol_iterator PI = I->protocol_begin(), | 
 | 921 |          E = I->protocol_end(); PI != E; ++PI) | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 922 |       MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen, | 
 | 923 |                                  IMPDecl, | 
| Fariborz Jahanian | b33f3ad | 2009-05-01 20:07:12 +0000 | [diff] [blame] | 924 |                                  (*PI), IncompleteImpl, false); | 
 | 925 |     if (I->getSuperClass()) | 
 | 926 |       MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen, | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 927 |                                  IMPDecl, | 
| Fariborz Jahanian | b33f3ad | 2009-05-01 20:07:12 +0000 | [diff] [blame] | 928 |                                  I->getSuperClass(), IncompleteImpl, false); | 
 | 929 |   } | 
 | 930 | } | 
 | 931 |  | 
| Fariborz Jahanian | 17cb326 | 2010-05-05 21:52:17 +0000 | [diff] [blame] | 932 | void Sema::ImplMethodsVsClassMethods(Scope *S, ObjCImplDecl* IMPDecl, | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 933 |                                      ObjCContainerDecl* CDecl, | 
| Chris Lattner | cddc888 | 2009-03-01 00:56:52 +0000 | [diff] [blame] | 934 |                                      bool IncompleteImpl) { | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 935 |   llvm::DenseSet<Selector> InsMap; | 
 | 936 |   // Check and see if instance methods in class interface have been | 
 | 937 |   // implemented in the implementation class. | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 938 |   for (ObjCImplementationDecl::instmeth_iterator | 
| Argyrios Kyrtzidis | 17945a0 | 2009-06-30 02:36:12 +0000 | [diff] [blame] | 939 |          I = IMPDecl->instmeth_begin(), E = IMPDecl->instmeth_end(); I!=E; ++I) | 
| Chris Lattner | 4c52509 | 2007-12-12 17:58:05 +0000 | [diff] [blame] | 940 |     InsMap.insert((*I)->getSelector()); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 941 |  | 
| Fariborz Jahanian | 12bac25 | 2009-04-14 23:15:21 +0000 | [diff] [blame] | 942 |   // Check and see if properties declared in the interface have either 1) | 
 | 943 |   // an implementation or 2) there is a @synthesize/@dynamic implementation | 
 | 944 |   // of the property in the @implementation. | 
| Fariborz Jahanian | 509d477 | 2010-05-14 18:35:57 +0000 | [diff] [blame] | 945 |   if (isa<ObjCInterfaceDecl>(CDecl) && !LangOpts.ObjCNonFragileABI2) | 
| Fariborz Jahanian | 17cb326 | 2010-05-05 21:52:17 +0000 | [diff] [blame] | 946 |     DiagnoseUnimplementedProperties(S, IMPDecl, CDecl, InsMap); | 
| Fariborz Jahanian | 3ac1eda | 2010-01-20 01:51:55 +0000 | [diff] [blame] | 947 |        | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 948 |   llvm::DenseSet<Selector> ClsMap; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 949 |   for (ObjCImplementationDecl::classmeth_iterator | 
| Argyrios Kyrtzidis | 17945a0 | 2009-06-30 02:36:12 +0000 | [diff] [blame] | 950 |        I = IMPDecl->classmeth_begin(), | 
 | 951 |        E = IMPDecl->classmeth_end(); I != E; ++I) | 
| Chris Lattner | 4c52509 | 2007-12-12 17:58:05 +0000 | [diff] [blame] | 952 |     ClsMap.insert((*I)->getSelector()); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 953 |  | 
| Fariborz Jahanian | b33f3ad | 2009-05-01 20:07:12 +0000 | [diff] [blame] | 954 |   // Check for type conflict of methods declared in a class/protocol and | 
 | 955 |   // its implementation; if any. | 
 | 956 |   llvm::DenseSet<Selector> InsMapSeen, ClsMapSeen; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 957 |   MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen, | 
 | 958 |                              IMPDecl, CDecl, | 
| Fariborz Jahanian | b33f3ad | 2009-05-01 20:07:12 +0000 | [diff] [blame] | 959 |                              IncompleteImpl, true); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 960 |  | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 961 |   // Check the protocol list for unimplemented methods in the @implementation | 
 | 962 |   // class. | 
| Fariborz Jahanian | b33f3ad | 2009-05-01 20:07:12 +0000 | [diff] [blame] | 963 |   // Check and see if class methods in class interface have been | 
 | 964 |   // implemented in the implementation class. | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 965 |  | 
| Chris Lattner | cddc888 | 2009-03-01 00:56:52 +0000 | [diff] [blame] | 966 |   if (ObjCInterfaceDecl *I = dyn_cast<ObjCInterfaceDecl> (CDecl)) { | 
| Fariborz Jahanian | b33f3ad | 2009-05-01 20:07:12 +0000 | [diff] [blame] | 967 |     for (ObjCInterfaceDecl::protocol_iterator PI = I->protocol_begin(), | 
| Chris Lattner | cddc888 | 2009-03-01 00:56:52 +0000 | [diff] [blame] | 968 |          E = I->protocol_end(); PI != E; ++PI) | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 969 |       CheckProtocolMethodDefs(IMPDecl->getLocation(), *PI, IncompleteImpl, | 
| Chris Lattner | cddc888 | 2009-03-01 00:56:52 +0000 | [diff] [blame] | 970 |                               InsMap, ClsMap, I); | 
 | 971 |     // Check class extensions (unnamed categories) | 
 | 972 |     for (ObjCCategoryDecl *Categories = I->getCategoryList(); | 
 | 973 |          Categories; Categories = Categories->getNextClassCategory()) { | 
| Fariborz Jahanian | 2576061 | 2010-02-15 21:55:26 +0000 | [diff] [blame] | 974 |       if (Categories->IsClassExtension()) { | 
| Fariborz Jahanian | 17cb326 | 2010-05-05 21:52:17 +0000 | [diff] [blame] | 975 |         ImplMethodsVsClassMethods(S, IMPDecl, Categories, IncompleteImpl); | 
| Chris Lattner | cddc888 | 2009-03-01 00:56:52 +0000 | [diff] [blame] | 976 |         break; | 
 | 977 |       } | 
| Fariborz Jahanian | 8daab97 | 2008-12-05 18:18:52 +0000 | [diff] [blame] | 978 |     } | 
| Chris Lattner | cddc888 | 2009-03-01 00:56:52 +0000 | [diff] [blame] | 979 |   } else if (ObjCCategoryDecl *C = dyn_cast<ObjCCategoryDecl>(CDecl)) { | 
| Fariborz Jahanian | b106fc6 | 2009-10-05 21:32:49 +0000 | [diff] [blame] | 980 |     // For extended class, unimplemented methods in its protocols will | 
 | 981 |     // be reported in the primary class. | 
| Fariborz Jahanian | 2576061 | 2010-02-15 21:55:26 +0000 | [diff] [blame] | 982 |     if (!C->IsClassExtension()) { | 
| Fariborz Jahanian | b106fc6 | 2009-10-05 21:32:49 +0000 | [diff] [blame] | 983 |       for (ObjCCategoryDecl::protocol_iterator PI = C->protocol_begin(), | 
 | 984 |            E = C->protocol_end(); PI != E; ++PI) | 
 | 985 |         CheckProtocolMethodDefs(IMPDecl->getLocation(), *PI, IncompleteImpl, | 
| Fariborz Jahanian | f283859 | 2010-03-27 21:10:05 +0000 | [diff] [blame] | 986 |                                 InsMap, ClsMap, CDecl); | 
| Fariborz Jahanian | 3ad230e | 2010-01-20 19:36:21 +0000 | [diff] [blame] | 987 |       // Report unimplemented properties in the category as well. | 
 | 988 |       // When reporting on missing setter/getters, do not report when | 
 | 989 |       // setter/getter is implemented in category's primary class  | 
 | 990 |       // implementation. | 
 | 991 |       if (ObjCInterfaceDecl *ID = C->getClassInterface()) | 
 | 992 |         if (ObjCImplDecl *IMP = ID->getImplementation()) { | 
 | 993 |           for (ObjCImplementationDecl::instmeth_iterator | 
 | 994 |                I = IMP->instmeth_begin(), E = IMP->instmeth_end(); I!=E; ++I) | 
 | 995 |             InsMap.insert((*I)->getSelector()); | 
 | 996 |         } | 
| Fariborz Jahanian | 17cb326 | 2010-05-05 21:52:17 +0000 | [diff] [blame] | 997 |       DiagnoseUnimplementedProperties(S, IMPDecl, CDecl, InsMap);       | 
| Fariborz Jahanian | 3ad230e | 2010-01-20 19:36:21 +0000 | [diff] [blame] | 998 |     }  | 
| Chris Lattner | cddc888 | 2009-03-01 00:56:52 +0000 | [diff] [blame] | 999 |   } else | 
 | 1000 |     assert(false && "invalid ObjCContainerDecl type."); | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 1001 | } | 
 | 1002 |  | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1003 | /// ActOnForwardClassDeclaration - | 
| Chris Lattner | b28317a | 2009-03-28 19:18:32 +0000 | [diff] [blame] | 1004 | Action::DeclPtrTy | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 1005 | Sema::ActOnForwardClassDeclaration(SourceLocation AtClassLoc, | 
| Chris Lattner | bdbde4d | 2009-02-16 19:25:52 +0000 | [diff] [blame] | 1006 |                                    IdentifierInfo **IdentList, | 
| Ted Kremenek | c09cba6 | 2009-11-17 23:12:20 +0000 | [diff] [blame] | 1007 |                                    SourceLocation *IdentLocs, | 
| Chris Lattner | bdbde4d | 2009-02-16 19:25:52 +0000 | [diff] [blame] | 1008 |                                    unsigned NumElts) { | 
| Ted Kremenek | a526c5c | 2008-01-07 19:49:32 +0000 | [diff] [blame] | 1009 |   llvm::SmallVector<ObjCInterfaceDecl*, 32> Interfaces; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1010 |  | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 1011 |   for (unsigned i = 0; i != NumElts; ++i) { | 
 | 1012 |     // Check for another declaration kind with the same name. | 
| John McCall | f36e02d | 2009-10-09 21:13:30 +0000 | [diff] [blame] | 1013 |     NamedDecl *PrevDecl | 
| Douglas Gregor | c83c687 | 2010-04-15 22:33:43 +0000 | [diff] [blame] | 1014 |       = LookupSingleName(TUScope, IdentList[i], IdentLocs[i],  | 
| Douglas Gregor | c0b3964 | 2010-04-15 23:40:53 +0000 | [diff] [blame] | 1015 |                          LookupOrdinaryName, ForRedeclaration); | 
| Douglas Gregor | f57172b | 2008-12-08 18:40:42 +0000 | [diff] [blame] | 1016 |     if (PrevDecl && PrevDecl->isTemplateParameter()) { | 
| Douglas Gregor | 72c3f31 | 2008-12-05 18:15:24 +0000 | [diff] [blame] | 1017 |       // Maybe we will complain about the shadowed template parameter. | 
 | 1018 |       DiagnoseTemplateParameterShadow(AtClassLoc, PrevDecl); | 
 | 1019 |       // Just pretend that we didn't see the previous declaration. | 
 | 1020 |       PrevDecl = 0; | 
 | 1021 |     } | 
 | 1022 |  | 
| Ted Kremenek | a526c5c | 2008-01-07 19:49:32 +0000 | [diff] [blame] | 1023 |     if (PrevDecl && !isa<ObjCInterfaceDecl>(PrevDecl)) { | 
| Steve Naroff | c733388 | 2008-06-05 22:57:10 +0000 | [diff] [blame] | 1024 |       // GCC apparently allows the following idiom: | 
 | 1025 |       // | 
 | 1026 |       // typedef NSObject < XCElementTogglerP > XCElementToggler; | 
 | 1027 |       // @class XCElementToggler; | 
 | 1028 |       // | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1029 |       // FIXME: Make an extension? | 
| Steve Naroff | c733388 | 2008-06-05 22:57:10 +0000 | [diff] [blame] | 1030 |       TypedefDecl *TDD = dyn_cast<TypedefDecl>(PrevDecl); | 
| John McCall | c12c5bb | 2010-05-15 11:32:37 +0000 | [diff] [blame] | 1031 |       if (!TDD || !TDD->getUnderlyingType()->isObjCObjectType()) { | 
| Chris Lattner | 3c73c41 | 2008-11-19 08:23:25 +0000 | [diff] [blame] | 1032 |         Diag(AtClassLoc, diag::err_redefinition_different_kind) << IdentList[i]; | 
| Chris Lattner | 5f4a682 | 2008-11-23 23:12:31 +0000 | [diff] [blame] | 1033 |         Diag(PrevDecl->getLocation(), diag::note_previous_definition); | 
| John McCall | c12c5bb | 2010-05-15 11:32:37 +0000 | [diff] [blame] | 1034 |       } else { | 
| Mike Stump | ac5fc7c | 2009-08-04 21:02:39 +0000 | [diff] [blame] | 1035 |         // a forward class declaration matching a typedef name of a class refers | 
 | 1036 |         // to the underlying class. | 
| John McCall | c12c5bb | 2010-05-15 11:32:37 +0000 | [diff] [blame] | 1037 |         if (const ObjCObjectType *OI = | 
 | 1038 |               TDD->getUnderlyingType()->getAs<ObjCObjectType>()) | 
 | 1039 |           PrevDecl = OI->getInterface(); | 
| Fariborz Jahanian | cae27c5 | 2009-05-07 21:49:26 +0000 | [diff] [blame] | 1040 |       } | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 1041 |     } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1042 |     ObjCInterfaceDecl *IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl); | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 1043 |     if (!IDecl) {  // Not already seen?  Make a forward decl. | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1044 |       IDecl = ObjCInterfaceDecl::Create(Context, CurContext, AtClassLoc, | 
| Ted Kremenek | 321c22f | 2009-11-18 00:28:11 +0000 | [diff] [blame] | 1045 |                                         IdentList[i], IdentLocs[i], true); | 
| Ted Kremenek | c32b1d8 | 2009-11-17 22:58:30 +0000 | [diff] [blame] | 1046 |        | 
 | 1047 |       // Push the ObjCInterfaceDecl on the scope chain but do *not* add it to | 
 | 1048 |       // the current DeclContext.  This prevents clients that walk DeclContext | 
 | 1049 |       // from seeing the imaginary ObjCInterfaceDecl until it is actually | 
 | 1050 |       // declared later (if at all).  We also take care to explicitly make | 
 | 1051 |       // sure this declaration is visible for name lookup. | 
 | 1052 |       PushOnScopeChains(IDecl, TUScope, false); | 
 | 1053 |       CurContext->makeDeclVisibleInContext(IDecl, true); | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 1054 |     } | 
 | 1055 |  | 
 | 1056 |     Interfaces.push_back(IDecl); | 
 | 1057 |   } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1058 |  | 
| Ted Kremenek | 321c22f | 2009-11-18 00:28:11 +0000 | [diff] [blame] | 1059 |   assert(Interfaces.size() == NumElts); | 
| Douglas Gregor | d043410 | 2009-01-09 00:49:46 +0000 | [diff] [blame] | 1060 |   ObjCClassDecl *CDecl = ObjCClassDecl::Create(Context, CurContext, AtClassLoc, | 
| Ted Kremenek | 321c22f | 2009-11-18 00:28:11 +0000 | [diff] [blame] | 1061 |                                                Interfaces.data(), IdentLocs, | 
| Anders Carlsson | 1528145 | 2008-11-04 16:57:32 +0000 | [diff] [blame] | 1062 |                                                Interfaces.size()); | 
| Argyrios Kyrtzidis | 17945a0 | 2009-06-30 02:36:12 +0000 | [diff] [blame] | 1063 |   CurContext->addDecl(CDecl); | 
| Anders Carlsson | 1528145 | 2008-11-04 16:57:32 +0000 | [diff] [blame] | 1064 |   CheckObjCDeclScope(CDecl); | 
| Chris Lattner | b28317a | 2009-03-28 19:18:32 +0000 | [diff] [blame] | 1065 |   return DeclPtrTy::make(CDecl); | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 1066 | } | 
 | 1067 |  | 
 | 1068 |  | 
 | 1069 | /// MatchTwoMethodDeclarations - Checks that two methods have matching type and | 
 | 1070 | /// returns true, or false, accordingly. | 
 | 1071 | /// TODO: Handle protocol list; such as id<p1,p2> in type comparisons | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1072 | bool Sema::MatchTwoMethodDeclarations(const ObjCMethodDecl *Method, | 
| Steve Naroff | fe6b0dc | 2008-10-21 10:37:50 +0000 | [diff] [blame] | 1073 |                                       const ObjCMethodDecl *PrevMethod, | 
 | 1074 |                                       bool matchBasedOnSizeAndAlignment) { | 
 | 1075 |   QualType T1 = Context.getCanonicalType(Method->getResultType()); | 
 | 1076 |   QualType T2 = Context.getCanonicalType(PrevMethod->getResultType()); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1077 |  | 
| Steve Naroff | fe6b0dc | 2008-10-21 10:37:50 +0000 | [diff] [blame] | 1078 |   if (T1 != T2) { | 
 | 1079 |     // The result types are different. | 
 | 1080 |     if (!matchBasedOnSizeAndAlignment) | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 1081 |       return false; | 
| Steve Naroff | fe6b0dc | 2008-10-21 10:37:50 +0000 | [diff] [blame] | 1082 |     // Incomplete types don't have a size and alignment. | 
 | 1083 |     if (T1->isIncompleteType() || T2->isIncompleteType()) | 
 | 1084 |       return false; | 
 | 1085 |     // Check is based on size and alignment. | 
 | 1086 |     if (Context.getTypeInfo(T1) != Context.getTypeInfo(T2)) | 
 | 1087 |       return false; | 
 | 1088 |   } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1089 |  | 
| Chris Lattner | 89951a8 | 2009-02-20 18:43:26 +0000 | [diff] [blame] | 1090 |   ObjCMethodDecl::param_iterator ParamI = Method->param_begin(), | 
 | 1091 |        E = Method->param_end(); | 
 | 1092 |   ObjCMethodDecl::param_iterator PrevI = PrevMethod->param_begin(); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1093 |  | 
| Chris Lattner | 89951a8 | 2009-02-20 18:43:26 +0000 | [diff] [blame] | 1094 |   for (; ParamI != E; ++ParamI, ++PrevI) { | 
 | 1095 |     assert(PrevI != PrevMethod->param_end() && "Param mismatch"); | 
 | 1096 |     T1 = Context.getCanonicalType((*ParamI)->getType()); | 
 | 1097 |     T2 = Context.getCanonicalType((*PrevI)->getType()); | 
| Steve Naroff | fe6b0dc | 2008-10-21 10:37:50 +0000 | [diff] [blame] | 1098 |     if (T1 != T2) { | 
 | 1099 |       // The result types are different. | 
 | 1100 |       if (!matchBasedOnSizeAndAlignment) | 
 | 1101 |         return false; | 
 | 1102 |       // Incomplete types don't have a size and alignment. | 
 | 1103 |       if (T1->isIncompleteType() || T2->isIncompleteType()) | 
 | 1104 |         return false; | 
 | 1105 |       // Check is based on size and alignment. | 
 | 1106 |       if (Context.getTypeInfo(T1) != Context.getTypeInfo(T2)) | 
 | 1107 |         return false; | 
 | 1108 |     } | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 1109 |   } | 
 | 1110 |   return true; | 
 | 1111 | } | 
 | 1112 |  | 
| Douglas Gregor | f0aaf7a | 2009-04-24 21:10:55 +0000 | [diff] [blame] | 1113 | /// \brief Read the contents of the instance and factory method pools | 
 | 1114 | /// for a given selector from external storage. | 
 | 1115 | /// | 
 | 1116 | /// This routine should only be called once, when neither the instance | 
 | 1117 | /// nor the factory method pool has an entry for this selector. | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1118 | Sema::MethodPool::iterator Sema::ReadMethodPool(Selector Sel, | 
| Douglas Gregor | f0aaf7a | 2009-04-24 21:10:55 +0000 | [diff] [blame] | 1119 |                                                 bool isInstance) { | 
 | 1120 |   assert(ExternalSource && "We need an external AST source"); | 
 | 1121 |   assert(InstanceMethodPool.find(Sel) == InstanceMethodPool.end() && | 
 | 1122 |          "Selector data already loaded into the instance method pool"); | 
 | 1123 |   assert(FactoryMethodPool.find(Sel) == FactoryMethodPool.end() && | 
 | 1124 |          "Selector data already loaded into the factory method pool"); | 
 | 1125 |  | 
 | 1126 |   // Read the method list from the external source. | 
 | 1127 |   std::pair<ObjCMethodList, ObjCMethodList> Methods | 
 | 1128 |     = ExternalSource->ReadMethodPool(Sel); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1129 |  | 
| Douglas Gregor | f0aaf7a | 2009-04-24 21:10:55 +0000 | [diff] [blame] | 1130 |   if (isInstance) { | 
 | 1131 |     if (Methods.second.Method) | 
 | 1132 |       FactoryMethodPool[Sel] = Methods.second; | 
 | 1133 |     return InstanceMethodPool.insert(std::make_pair(Sel, Methods.first)).first; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1134 |   } | 
| Douglas Gregor | f0aaf7a | 2009-04-24 21:10:55 +0000 | [diff] [blame] | 1135 |  | 
 | 1136 |   if (Methods.first.Method) | 
 | 1137 |     InstanceMethodPool[Sel] = Methods.first; | 
 | 1138 |  | 
 | 1139 |   return FactoryMethodPool.insert(std::make_pair(Sel, Methods.second)).first; | 
 | 1140 | } | 
 | 1141 |  | 
| Ted Kremenek | a526c5c | 2008-01-07 19:49:32 +0000 | [diff] [blame] | 1142 | void Sema::AddInstanceMethodToGlobalPool(ObjCMethodDecl *Method) { | 
| Douglas Gregor | f0aaf7a | 2009-04-24 21:10:55 +0000 | [diff] [blame] | 1143 |   llvm::DenseMap<Selector, ObjCMethodList>::iterator Pos | 
 | 1144 |     = InstanceMethodPool.find(Method->getSelector()); | 
 | 1145 |   if (Pos == InstanceMethodPool.end()) { | 
 | 1146 |     if (ExternalSource && !FactoryMethodPool.count(Method->getSelector())) | 
 | 1147 |       Pos = ReadMethodPool(Method->getSelector(), /*isInstance=*/true); | 
 | 1148 |     else | 
 | 1149 |       Pos = InstanceMethodPool.insert(std::make_pair(Method->getSelector(), | 
 | 1150 |                                                      ObjCMethodList())).first; | 
 | 1151 |   } | 
 | 1152 |  | 
 | 1153 |   ObjCMethodList &Entry = Pos->second; | 
| Chris Lattner | b25df35 | 2009-03-04 05:16:45 +0000 | [diff] [blame] | 1154 |   if (Entry.Method == 0) { | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 1155 |     // Haven't seen a method with this selector name yet - add it. | 
| Chris Lattner | b25df35 | 2009-03-04 05:16:45 +0000 | [diff] [blame] | 1156 |     Entry.Method = Method; | 
 | 1157 |     Entry.Next = 0; | 
 | 1158 |     return; | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 1159 |   } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1160 |  | 
| Chris Lattner | b25df35 | 2009-03-04 05:16:45 +0000 | [diff] [blame] | 1161 |   // We've seen a method with this name, see if we have already seen this type | 
 | 1162 |   // signature. | 
 | 1163 |   for (ObjCMethodList *List = &Entry; List; List = List->Next) | 
 | 1164 |     if (MatchTwoMethodDeclarations(Method, List->Method)) | 
 | 1165 |       return; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1166 |  | 
| Chris Lattner | b25df35 | 2009-03-04 05:16:45 +0000 | [diff] [blame] | 1167 |   // We have a new signature for an existing method - add it. | 
 | 1168 |   // This is extremely rare. Only 1% of Cocoa selectors are "overloaded". | 
| Ted Kremenek | 298ed87 | 2010-02-11 00:53:01 +0000 | [diff] [blame] | 1169 |   ObjCMethodList *Mem = BumpAlloc.Allocate<ObjCMethodList>(); | 
 | 1170 |   Entry.Next = new (Mem) ObjCMethodList(Method, Entry.Next); | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 1171 | } | 
 | 1172 |  | 
| Steve Naroff | 6f5f41c | 2008-10-21 10:50:19 +0000 | [diff] [blame] | 1173 | // FIXME: Finish implementing -Wno-strict-selector-match. | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1174 | ObjCMethodDecl *Sema::LookupInstanceMethodInGlobalPool(Selector Sel, | 
| Fariborz Jahanian | 835ed7f | 2009-08-22 21:13:55 +0000 | [diff] [blame] | 1175 |                                                        SourceRange R, | 
 | 1176 |                                                        bool warn) { | 
| Douglas Gregor | f0aaf7a | 2009-04-24 21:10:55 +0000 | [diff] [blame] | 1177 |   llvm::DenseMap<Selector, ObjCMethodList>::iterator Pos | 
 | 1178 |     = InstanceMethodPool.find(Sel); | 
| Douglas Gregor | 27a4566 | 2009-04-24 22:23:41 +0000 | [diff] [blame] | 1179 |   if (Pos == InstanceMethodPool.end()) { | 
 | 1180 |     if (ExternalSource && !FactoryMethodPool.count(Sel)) | 
| Douglas Gregor | f0aaf7a | 2009-04-24 21:10:55 +0000 | [diff] [blame] | 1181 |       Pos = ReadMethodPool(Sel, /*isInstance=*/true); | 
 | 1182 |     else | 
 | 1183 |       return 0; | 
 | 1184 |   } | 
 | 1185 |  | 
 | 1186 |   ObjCMethodList &MethList = Pos->second; | 
| Steve Naroff | fe6b0dc | 2008-10-21 10:37:50 +0000 | [diff] [blame] | 1187 |   bool issueWarning = false; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1188 |  | 
| Steve Naroff | 037cda5 | 2008-09-30 14:38:43 +0000 | [diff] [blame] | 1189 |   if (MethList.Method && MethList.Next) { | 
| Steve Naroff | fe6b0dc | 2008-10-21 10:37:50 +0000 | [diff] [blame] | 1190 |     for (ObjCMethodList *Next = MethList.Next; Next; Next = Next->Next) | 
 | 1191 |       // This checks if the methods differ by size & alignment. | 
 | 1192 |       if (!MatchTwoMethodDeclarations(MethList.Method, Next->Method, true)) | 
| Fariborz Jahanian | 835ed7f | 2009-08-22 21:13:55 +0000 | [diff] [blame] | 1193 |         issueWarning = warn; | 
| Steve Naroff | fe6b0dc | 2008-10-21 10:37:50 +0000 | [diff] [blame] | 1194 |   } | 
 | 1195 |   if (issueWarning && (MethList.Method && MethList.Next)) { | 
| Chris Lattner | 077bf5e | 2008-11-24 03:33:13 +0000 | [diff] [blame] | 1196 |     Diag(R.getBegin(), diag::warn_multiple_method_decl) << Sel << R; | 
| John McCall | 41ce66f | 2009-12-10 19:51:03 +0000 | [diff] [blame] | 1197 |     Diag(MethList.Method->getLocStart(), diag::note_using) | 
| Chris Lattner | dcd5ef1 | 2008-11-19 05:27:50 +0000 | [diff] [blame] | 1198 |       << MethList.Method->getSourceRange(); | 
| Steve Naroff | 037cda5 | 2008-09-30 14:38:43 +0000 | [diff] [blame] | 1199 |     for (ObjCMethodList *Next = MethList.Next; Next; Next = Next->Next) | 
| John McCall | 41ce66f | 2009-12-10 19:51:03 +0000 | [diff] [blame] | 1200 |       Diag(Next->Method->getLocStart(), diag::note_also_found) | 
| Chris Lattner | dcd5ef1 | 2008-11-19 05:27:50 +0000 | [diff] [blame] | 1201 |         << Next->Method->getSourceRange(); | 
| Steve Naroff | 037cda5 | 2008-09-30 14:38:43 +0000 | [diff] [blame] | 1202 |   } | 
 | 1203 |   return MethList.Method; | 
 | 1204 | } | 
 | 1205 |  | 
| Ted Kremenek | a526c5c | 2008-01-07 19:49:32 +0000 | [diff] [blame] | 1206 | void Sema::AddFactoryMethodToGlobalPool(ObjCMethodDecl *Method) { | 
| Douglas Gregor | f0aaf7a | 2009-04-24 21:10:55 +0000 | [diff] [blame] | 1207 |   llvm::DenseMap<Selector, ObjCMethodList>::iterator Pos | 
 | 1208 |     = FactoryMethodPool.find(Method->getSelector()); | 
 | 1209 |   if (Pos == FactoryMethodPool.end()) { | 
 | 1210 |     if (ExternalSource && !InstanceMethodPool.count(Method->getSelector())) | 
 | 1211 |       Pos = ReadMethodPool(Method->getSelector(), /*isInstance=*/false); | 
 | 1212 |     else | 
 | 1213 |       Pos = FactoryMethodPool.insert(std::make_pair(Method->getSelector(), | 
 | 1214 |                                                     ObjCMethodList())).first; | 
 | 1215 |   } | 
 | 1216 |  | 
 | 1217 |   ObjCMethodList &FirstMethod = Pos->second; | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 1218 |   if (!FirstMethod.Method) { | 
 | 1219 |     // Haven't seen a method with this selector name yet - add it. | 
 | 1220 |     FirstMethod.Method = Method; | 
 | 1221 |     FirstMethod.Next = 0; | 
 | 1222 |   } else { | 
 | 1223 |     // We've seen a method with this name, now check the type signature(s). | 
 | 1224 |     bool match = MatchTwoMethodDeclarations(Method, FirstMethod.Method); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1225 |  | 
 | 1226 |     for (ObjCMethodList *Next = FirstMethod.Next; !match && Next; | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 1227 |          Next = Next->Next) | 
 | 1228 |       match = MatchTwoMethodDeclarations(Method, Next->Method); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1229 |  | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 1230 |     if (!match) { | 
 | 1231 |       // We have a new signature for an existing method - add it. | 
 | 1232 |       // This is extremely rare. Only 1% of Cocoa selectors are "overloaded". | 
| Ted Kremenek | 298ed87 | 2010-02-11 00:53:01 +0000 | [diff] [blame] | 1233 |       ObjCMethodList *Mem = BumpAlloc.Allocate<ObjCMethodList>(); | 
 | 1234 |       ObjCMethodList *OMI = new (Mem) ObjCMethodList(Method, FirstMethod.Next); | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 1235 |       FirstMethod.Next = OMI; | 
 | 1236 |     } | 
 | 1237 |   } | 
 | 1238 | } | 
 | 1239 |  | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1240 | ObjCMethodDecl *Sema::LookupFactoryMethodInGlobalPool(Selector Sel, | 
| Douglas Gregor | f0aaf7a | 2009-04-24 21:10:55 +0000 | [diff] [blame] | 1241 |                                                       SourceRange R) { | 
 | 1242 |   llvm::DenseMap<Selector, ObjCMethodList>::iterator Pos | 
 | 1243 |     = FactoryMethodPool.find(Sel); | 
 | 1244 |   if (Pos == FactoryMethodPool.end()) { | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1245 |     if (ExternalSource && !InstanceMethodPool.count(Sel)) | 
| Douglas Gregor | f0aaf7a | 2009-04-24 21:10:55 +0000 | [diff] [blame] | 1246 |       Pos = ReadMethodPool(Sel, /*isInstance=*/false); | 
 | 1247 |     else | 
 | 1248 |       return 0; | 
 | 1249 |   } | 
 | 1250 |  | 
 | 1251 |   ObjCMethodList &MethList = Pos->second; | 
 | 1252 |   bool issueWarning = false; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1253 |  | 
| Douglas Gregor | f0aaf7a | 2009-04-24 21:10:55 +0000 | [diff] [blame] | 1254 |   if (MethList.Method && MethList.Next) { | 
 | 1255 |     for (ObjCMethodList *Next = MethList.Next; Next; Next = Next->Next) | 
 | 1256 |       // This checks if the methods differ by size & alignment. | 
 | 1257 |       if (!MatchTwoMethodDeclarations(MethList.Method, Next->Method, true)) | 
 | 1258 |         issueWarning = true; | 
 | 1259 |   } | 
 | 1260 |   if (issueWarning && (MethList.Method && MethList.Next)) { | 
 | 1261 |     Diag(R.getBegin(), diag::warn_multiple_method_decl) << Sel << R; | 
| John McCall | 41ce66f | 2009-12-10 19:51:03 +0000 | [diff] [blame] | 1262 |     Diag(MethList.Method->getLocStart(), diag::note_using) | 
| Douglas Gregor | f0aaf7a | 2009-04-24 21:10:55 +0000 | [diff] [blame] | 1263 |       << MethList.Method->getSourceRange(); | 
 | 1264 |     for (ObjCMethodList *Next = MethList.Next; Next; Next = Next->Next) | 
| John McCall | 41ce66f | 2009-12-10 19:51:03 +0000 | [diff] [blame] | 1265 |       Diag(Next->Method->getLocStart(), diag::note_also_found) | 
| Douglas Gregor | f0aaf7a | 2009-04-24 21:10:55 +0000 | [diff] [blame] | 1266 |         << Next->Method->getSourceRange(); | 
 | 1267 |   } | 
 | 1268 |   return MethList.Method; | 
 | 1269 | } | 
 | 1270 |  | 
| Fariborz Jahanian | e198f5d | 2009-08-04 17:01:09 +0000 | [diff] [blame] | 1271 | /// CompareMethodParamsInBaseAndSuper - This routine compares methods with | 
 | 1272 | /// identical selector names in current and its super classes and issues | 
 | 1273 | /// a warning if any of their argument types are incompatible. | 
| Fariborz Jahanian | dbdec8b | 2009-08-04 01:07:16 +0000 | [diff] [blame] | 1274 | void Sema::CompareMethodParamsInBaseAndSuper(Decl *ClassDecl, | 
 | 1275 |                                              ObjCMethodDecl *Method, | 
 | 1276 |                                              bool IsInstance)  { | 
| Fariborz Jahanian | e198f5d | 2009-08-04 17:01:09 +0000 | [diff] [blame] | 1277 |   ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(ClassDecl); | 
 | 1278 |   if (ID == 0) return; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1279 |  | 
| Fariborz Jahanian | e198f5d | 2009-08-04 17:01:09 +0000 | [diff] [blame] | 1280 |   while (ObjCInterfaceDecl *SD = ID->getSuperClass()) { | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1281 |     ObjCMethodDecl *SuperMethodDecl = | 
| Fariborz Jahanian | e198f5d | 2009-08-04 17:01:09 +0000 | [diff] [blame] | 1282 |         SD->lookupMethod(Method->getSelector(), IsInstance); | 
 | 1283 |     if (SuperMethodDecl == 0) { | 
| Fariborz Jahanian | dbdec8b | 2009-08-04 01:07:16 +0000 | [diff] [blame] | 1284 |       ID = SD; | 
| Fariborz Jahanian | e198f5d | 2009-08-04 17:01:09 +0000 | [diff] [blame] | 1285 |       continue; | 
| Fariborz Jahanian | dbdec8b | 2009-08-04 01:07:16 +0000 | [diff] [blame] | 1286 |     } | 
| Fariborz Jahanian | e198f5d | 2009-08-04 17:01:09 +0000 | [diff] [blame] | 1287 |     ObjCMethodDecl::param_iterator ParamI = Method->param_begin(), | 
 | 1288 |       E = Method->param_end(); | 
 | 1289 |     ObjCMethodDecl::param_iterator PrevI = SuperMethodDecl->param_begin(); | 
 | 1290 |     for (; ParamI != E; ++ParamI, ++PrevI) { | 
 | 1291 |       // Number of parameters are the same and is guaranteed by selector match. | 
 | 1292 |       assert(PrevI != SuperMethodDecl->param_end() && "Param mismatch"); | 
 | 1293 |       QualType T1 = Context.getCanonicalType((*ParamI)->getType()); | 
 | 1294 |       QualType T2 = Context.getCanonicalType((*PrevI)->getType()); | 
 | 1295 |       // If type of arguement of method in this class does not match its | 
 | 1296 |       // respective argument type in the super class method, issue warning; | 
 | 1297 |       if (!Context.typesAreCompatible(T1, T2)) { | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1298 |         Diag((*ParamI)->getLocation(), diag::ext_typecheck_base_super) | 
| Fariborz Jahanian | e198f5d | 2009-08-04 17:01:09 +0000 | [diff] [blame] | 1299 |           << T1 << T2; | 
 | 1300 |         Diag(SuperMethodDecl->getLocation(), diag::note_previous_declaration); | 
 | 1301 |         return; | 
 | 1302 |       } | 
 | 1303 |     } | 
 | 1304 |     ID = SD; | 
 | 1305 |   } | 
| Fariborz Jahanian | dbdec8b | 2009-08-04 01:07:16 +0000 | [diff] [blame] | 1306 | } | 
 | 1307 |  | 
| Fariborz Jahanian | f914b97 | 2010-02-23 23:41:11 +0000 | [diff] [blame] | 1308 | /// DiagnoseDuplicateIvars -  | 
 | 1309 | /// Check for duplicate ivars in the entire class at the start of  | 
 | 1310 | /// @implementation. This becomes necesssary because class extension can | 
 | 1311 | /// add ivars to a class in random order which will not be known until | 
 | 1312 | /// class's @implementation is seen. | 
 | 1313 | void Sema::DiagnoseDuplicateIvars(ObjCInterfaceDecl *ID,  | 
 | 1314 |                                   ObjCInterfaceDecl *SID) { | 
 | 1315 |   for (ObjCInterfaceDecl::ivar_iterator IVI = ID->ivar_begin(), | 
 | 1316 |        IVE = ID->ivar_end(); IVI != IVE; ++IVI) { | 
 | 1317 |     ObjCIvarDecl* Ivar = (*IVI); | 
 | 1318 |     if (Ivar->isInvalidDecl()) | 
 | 1319 |       continue; | 
 | 1320 |     if (IdentifierInfo *II = Ivar->getIdentifier()) { | 
 | 1321 |       ObjCIvarDecl* prevIvar = SID->lookupInstanceVariable(II); | 
 | 1322 |       if (prevIvar) { | 
 | 1323 |         Diag(Ivar->getLocation(), diag::err_duplicate_member) << II; | 
 | 1324 |         Diag(prevIvar->getLocation(), diag::note_previous_declaration); | 
 | 1325 |         Ivar->setInvalidDecl(); | 
 | 1326 |       } | 
 | 1327 |     } | 
 | 1328 |   } | 
 | 1329 | } | 
 | 1330 |  | 
| Steve Naroff | a56f616 | 2007-12-18 01:30:32 +0000 | [diff] [blame] | 1331 | // Note: For class/category implemenations, allMethods/allProperties is | 
 | 1332 | // always null. | 
| Fariborz Jahanian | 17cb326 | 2010-05-05 21:52:17 +0000 | [diff] [blame] | 1333 | void Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, | 
| Ted Kremenek | 782f2f5 | 2010-01-07 01:20:12 +0000 | [diff] [blame] | 1334 |                       DeclPtrTy classDecl, | 
| Chris Lattner | b28317a | 2009-03-28 19:18:32 +0000 | [diff] [blame] | 1335 |                       DeclPtrTy *allMethods, unsigned allNum, | 
 | 1336 |                       DeclPtrTy *allProperties, unsigned pNum, | 
| Chris Lattner | 682bf92 | 2009-03-29 16:50:03 +0000 | [diff] [blame] | 1337 |                       DeclGroupPtrTy *allTUVars, unsigned tuvNum) { | 
| Chris Lattner | b28317a | 2009-03-28 19:18:32 +0000 | [diff] [blame] | 1338 |   Decl *ClassDecl = classDecl.getAs<Decl>(); | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 1339 |  | 
| Steve Naroff | a56f616 | 2007-12-18 01:30:32 +0000 | [diff] [blame] | 1340 |   // FIXME: If we don't have a ClassDecl, we have an error. We should consider | 
 | 1341 |   // always passing in a decl. If the decl has an error, isInvalidDecl() | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 1342 |   // should be true. | 
 | 1343 |   if (!ClassDecl) | 
 | 1344 |     return; | 
| Fariborz Jahanian | 63e963c | 2009-11-16 18:57:01 +0000 | [diff] [blame] | 1345 |    | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1346 |   bool isInterfaceDeclKind = | 
| Chris Lattner | f8d17a5 | 2008-03-16 21:17:37 +0000 | [diff] [blame] | 1347 |         isa<ObjCInterfaceDecl>(ClassDecl) || isa<ObjCCategoryDecl>(ClassDecl) | 
 | 1348 |          || isa<ObjCProtocolDecl>(ClassDecl); | 
| Ted Kremenek | a526c5c | 2008-01-07 19:49:32 +0000 | [diff] [blame] | 1349 |   bool checkIdenticalMethods = isa<ObjCImplementationDecl>(ClassDecl); | 
| Steve Naroff | 09c4719 | 2009-01-09 15:36:25 +0000 | [diff] [blame] | 1350 |  | 
| Ted Kremenek | 782f2f5 | 2010-01-07 01:20:12 +0000 | [diff] [blame] | 1351 |   if (!isInterfaceDeclKind && AtEnd.isInvalid()) { | 
 | 1352 |     // FIXME: This is wrong.  We shouldn't be pretending that there is | 
 | 1353 |     //  an '@end' in the declaration. | 
 | 1354 |     SourceLocation L = ClassDecl->getLocation(); | 
 | 1355 |     AtEnd.setBegin(L); | 
 | 1356 |     AtEnd.setEnd(L); | 
 | 1357 |     Diag(L, diag::warn_missing_atend); | 
| Fariborz Jahanian | 63e963c | 2009-11-16 18:57:01 +0000 | [diff] [blame] | 1358 |   } | 
 | 1359 |    | 
| Steve Naroff | 0701bbb | 2009-01-08 17:28:14 +0000 | [diff] [blame] | 1360 |   DeclContext *DC = dyn_cast<DeclContext>(ClassDecl); | 
| Steve Naroff | 0701bbb | 2009-01-08 17:28:14 +0000 | [diff] [blame] | 1361 |  | 
 | 1362 |   // FIXME: Remove these and use the ObjCContainerDecl/DeclContext. | 
 | 1363 |   llvm::DenseMap<Selector, const ObjCMethodDecl*> InsMap; | 
 | 1364 |   llvm::DenseMap<Selector, const ObjCMethodDecl*> ClsMap; | 
 | 1365 |  | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 1366 |   for (unsigned i = 0; i < allNum; i++ ) { | 
| Ted Kremenek | a526c5c | 2008-01-07 19:49:32 +0000 | [diff] [blame] | 1367 |     ObjCMethodDecl *Method = | 
| Chris Lattner | b28317a | 2009-03-28 19:18:32 +0000 | [diff] [blame] | 1368 |       cast_or_null<ObjCMethodDecl>(allMethods[i].getAs<Decl>()); | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 1369 |  | 
 | 1370 |     if (!Method) continue;  // Already issued a diagnostic. | 
| Douglas Gregor | f8d49f6 | 2009-01-09 17:18:27 +0000 | [diff] [blame] | 1371 |     if (Method->isInstanceMethod()) { | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 1372 |       /// Check for instance method of the same name with incompatible types | 
| Ted Kremenek | a526c5c | 2008-01-07 19:49:32 +0000 | [diff] [blame] | 1373 |       const ObjCMethodDecl *&PrevMethod = InsMap[Method->getSelector()]; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1374 |       bool match = PrevMethod ? MatchTwoMethodDeclarations(Method, PrevMethod) | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 1375 |                               : false; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1376 |       if ((isInterfaceDeclKind && PrevMethod && !match) | 
| Eli Friedman | 82b4e76 | 2008-12-16 20:15:50 +0000 | [diff] [blame] | 1377 |           || (checkIdenticalMethods && match)) { | 
| Chris Lattner | 5f4a682 | 2008-11-23 23:12:31 +0000 | [diff] [blame] | 1378 |           Diag(Method->getLocation(), diag::err_duplicate_method_decl) | 
| Chris Lattner | 077bf5e | 2008-11-24 03:33:13 +0000 | [diff] [blame] | 1379 |             << Method->getDeclName(); | 
| Chris Lattner | 5f4a682 | 2008-11-23 23:12:31 +0000 | [diff] [blame] | 1380 |           Diag(PrevMethod->getLocation(), diag::note_previous_declaration); | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 1381 |       } else { | 
| Argyrios Kyrtzidis | 17945a0 | 2009-06-30 02:36:12 +0000 | [diff] [blame] | 1382 |         DC->addDecl(Method); | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 1383 |         InsMap[Method->getSelector()] = Method; | 
 | 1384 |         /// The following allows us to typecheck messages to "id". | 
 | 1385 |         AddInstanceMethodToGlobalPool(Method); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1386 |         // verify that the instance method conforms to the same definition of | 
| Fariborz Jahanian | e198f5d | 2009-08-04 17:01:09 +0000 | [diff] [blame] | 1387 |         // parent methods if it shadows one. | 
| Fariborz Jahanian | dbdec8b | 2009-08-04 01:07:16 +0000 | [diff] [blame] | 1388 |         CompareMethodParamsInBaseAndSuper(ClassDecl, Method, true); | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 1389 |       } | 
| Mike Stump | ac5fc7c | 2009-08-04 21:02:39 +0000 | [diff] [blame] | 1390 |     } else { | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 1391 |       /// Check for class method of the same name with incompatible types | 
| Ted Kremenek | a526c5c | 2008-01-07 19:49:32 +0000 | [diff] [blame] | 1392 |       const ObjCMethodDecl *&PrevMethod = ClsMap[Method->getSelector()]; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1393 |       bool match = PrevMethod ? MatchTwoMethodDeclarations(Method, PrevMethod) | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 1394 |                               : false; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1395 |       if ((isInterfaceDeclKind && PrevMethod && !match) | 
| Eli Friedman | 82b4e76 | 2008-12-16 20:15:50 +0000 | [diff] [blame] | 1396 |           || (checkIdenticalMethods && match)) { | 
| Chris Lattner | 5f4a682 | 2008-11-23 23:12:31 +0000 | [diff] [blame] | 1397 |         Diag(Method->getLocation(), diag::err_duplicate_method_decl) | 
| Chris Lattner | 077bf5e | 2008-11-24 03:33:13 +0000 | [diff] [blame] | 1398 |           << Method->getDeclName(); | 
| Chris Lattner | 5f4a682 | 2008-11-23 23:12:31 +0000 | [diff] [blame] | 1399 |         Diag(PrevMethod->getLocation(), diag::note_previous_declaration); | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 1400 |       } else { | 
| Argyrios Kyrtzidis | 17945a0 | 2009-06-30 02:36:12 +0000 | [diff] [blame] | 1401 |         DC->addDecl(Method); | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 1402 |         ClsMap[Method->getSelector()] = Method; | 
| Steve Naroff | a56f616 | 2007-12-18 01:30:32 +0000 | [diff] [blame] | 1403 |         /// The following allows us to typecheck messages to "Class". | 
 | 1404 |         AddFactoryMethodToGlobalPool(Method); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1405 |         // verify that the class method conforms to the same definition of | 
| Fariborz Jahanian | e198f5d | 2009-08-04 17:01:09 +0000 | [diff] [blame] | 1406 |         // parent methods if it shadows one. | 
| Fariborz Jahanian | dbdec8b | 2009-08-04 01:07:16 +0000 | [diff] [blame] | 1407 |         CompareMethodParamsInBaseAndSuper(ClassDecl, Method, false); | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 1408 |       } | 
 | 1409 |     } | 
 | 1410 |   } | 
| Ted Kremenek | a526c5c | 2008-01-07 19:49:32 +0000 | [diff] [blame] | 1411 |   if (ObjCInterfaceDecl *I = dyn_cast<ObjCInterfaceDecl>(ClassDecl)) { | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1412 |     // Compares properties declared in this class to those of its | 
| Fariborz Jahanian | 02edb98 | 2008-05-01 00:03:38 +0000 | [diff] [blame] | 1413 |     // super class. | 
| Fariborz Jahanian | aebf0cb | 2008-05-02 19:17:30 +0000 | [diff] [blame] | 1414 |     ComparePropertiesInBaseAndSuper(I); | 
| Fariborz Jahanian | 107089f | 2010-01-18 18:41:16 +0000 | [diff] [blame] | 1415 |     CompareProperties(I, DeclPtrTy::make(I)); | 
| Steve Naroff | 09c4719 | 2009-01-09 15:36:25 +0000 | [diff] [blame] | 1416 |   } else if (ObjCCategoryDecl *C = dyn_cast<ObjCCategoryDecl>(ClassDecl)) { | 
| Fariborz Jahanian | 77e14bd | 2008-12-06 19:59:02 +0000 | [diff] [blame] | 1417 |     // Categories are used to extend the class by declaring new methods. | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1418 |     // By the same token, they are also used to add new properties. No | 
| Fariborz Jahanian | 77e14bd | 2008-12-06 19:59:02 +0000 | [diff] [blame] | 1419 |     // need to compare the added property to those in the class. | 
| Daniel Dunbar | b20ef3e | 2008-08-27 05:40:03 +0000 | [diff] [blame] | 1420 |  | 
| Fariborz Jahanian | 107089f | 2010-01-18 18:41:16 +0000 | [diff] [blame] | 1421 |     // Compare protocol properties with those in category | 
 | 1422 |     CompareProperties(C, DeclPtrTy::make(C)); | 
| Fariborz Jahanian | 2576061 | 2010-02-15 21:55:26 +0000 | [diff] [blame] | 1423 |     if (C->IsClassExtension()) | 
| Fariborz Jahanian | b7f95f5 | 2009-03-02 19:05:07 +0000 | [diff] [blame] | 1424 |       DiagnoseClassExtensionDupMethods(C, C->getClassInterface()); | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 1425 |   } | 
| Steve Naroff | 09c4719 | 2009-01-09 15:36:25 +0000 | [diff] [blame] | 1426 |   if (ObjCContainerDecl *CDecl = dyn_cast<ObjCContainerDecl>(ClassDecl)) { | 
| Fariborz Jahanian | 2576061 | 2010-02-15 21:55:26 +0000 | [diff] [blame] | 1427 |     if (CDecl->getIdentifier()) | 
 | 1428 |       // ProcessPropertyDecl is responsible for diagnosing conflicts with any | 
 | 1429 |       // user-defined setter/getter. It also synthesizes setter/getter methods | 
 | 1430 |       // and adds them to the DeclContext and global method pools. | 
 | 1431 |       for (ObjCContainerDecl::prop_iterator I = CDecl->prop_begin(), | 
 | 1432 |                                             E = CDecl->prop_end(); | 
 | 1433 |            I != E; ++I) | 
 | 1434 |         ProcessPropertyDecl(*I, CDecl); | 
| Ted Kremenek | 782f2f5 | 2010-01-07 01:20:12 +0000 | [diff] [blame] | 1435 |     CDecl->setAtEndRange(AtEnd); | 
| Steve Naroff | 09c4719 | 2009-01-09 15:36:25 +0000 | [diff] [blame] | 1436 |   } | 
 | 1437 |   if (ObjCImplementationDecl *IC=dyn_cast<ObjCImplementationDecl>(ClassDecl)) { | 
| Ted Kremenek | 782f2f5 | 2010-01-07 01:20:12 +0000 | [diff] [blame] | 1438 |     IC->setAtEndRange(AtEnd); | 
| Fariborz Jahanian | 7ca8b06 | 2009-11-11 22:40:11 +0000 | [diff] [blame] | 1439 |     if (ObjCInterfaceDecl* IDecl = IC->getClassInterface()) { | 
| Fariborz Jahanian | 509d477 | 2010-05-14 18:35:57 +0000 | [diff] [blame] | 1440 |       if (LangOpts.ObjCNonFragileABI2) | 
 | 1441 |         DefaultSynthesizeProperties(S, IC, IDecl); | 
| Fariborz Jahanian | 17cb326 | 2010-05-05 21:52:17 +0000 | [diff] [blame] | 1442 |       ImplMethodsVsClassMethods(S, IC, IDecl); | 
| Fariborz Jahanian | 7ca8b06 | 2009-11-11 22:40:11 +0000 | [diff] [blame] | 1443 |       AtomicPropertySetterGetterRules(IC, IDecl); | 
| Fariborz Jahanian | f914b97 | 2010-02-23 23:41:11 +0000 | [diff] [blame] | 1444 |       if (LangOpts.ObjCNonFragileABI2) | 
 | 1445 |         while (IDecl->getSuperClass()) { | 
 | 1446 |           DiagnoseDuplicateIvars(IDecl, IDecl->getSuperClass()); | 
 | 1447 |           IDecl = IDecl->getSuperClass(); | 
 | 1448 |         } | 
| Fariborz Jahanian | 7ca8b06 | 2009-11-11 22:40:11 +0000 | [diff] [blame] | 1449 |     } | 
| Fariborz Jahanian | e4498c6 | 2010-04-28 16:11:27 +0000 | [diff] [blame] | 1450 |     SetIvarInitializers(IC); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1451 |   } else if (ObjCCategoryImplDecl* CatImplClass = | 
| Steve Naroff | 09c4719 | 2009-01-09 15:36:25 +0000 | [diff] [blame] | 1452 |                                    dyn_cast<ObjCCategoryImplDecl>(ClassDecl)) { | 
| Ted Kremenek | 782f2f5 | 2010-01-07 01:20:12 +0000 | [diff] [blame] | 1453 |     CatImplClass->setAtEndRange(AtEnd); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1454 |  | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 1455 |     // Find category interface decl and then check that all methods declared | 
| Daniel Dunbar | b20ef3e | 2008-08-27 05:40:03 +0000 | [diff] [blame] | 1456 |     // in this interface are implemented in the category @implementation. | 
| Chris Lattner | 97a5887 | 2009-02-16 18:32:47 +0000 | [diff] [blame] | 1457 |     if (ObjCInterfaceDecl* IDecl = CatImplClass->getClassInterface()) { | 
| Ted Kremenek | a526c5c | 2008-01-07 19:49:32 +0000 | [diff] [blame] | 1458 |       for (ObjCCategoryDecl *Categories = IDecl->getCategoryList(); | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 1459 |            Categories; Categories = Categories->getNextClassCategory()) { | 
 | 1460 |         if (Categories->getIdentifier() == CatImplClass->getIdentifier()) { | 
| Fariborz Jahanian | 17cb326 | 2010-05-05 21:52:17 +0000 | [diff] [blame] | 1461 |           ImplMethodsVsClassMethods(S, CatImplClass, Categories); | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 1462 |           break; | 
 | 1463 |         } | 
 | 1464 |       } | 
 | 1465 |     } | 
 | 1466 |   } | 
| Chris Lattner | 682bf92 | 2009-03-29 16:50:03 +0000 | [diff] [blame] | 1467 |   if (isInterfaceDeclKind) { | 
 | 1468 |     // Reject invalid vardecls. | 
 | 1469 |     for (unsigned i = 0; i != tuvNum; i++) { | 
 | 1470 |       DeclGroupRef DG = allTUVars[i].getAsVal<DeclGroupRef>(); | 
 | 1471 |       for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) | 
 | 1472 |         if (VarDecl *VDecl = dyn_cast<VarDecl>(*I)) { | 
| Daniel Dunbar | 5466c7b | 2009-04-14 02:25:56 +0000 | [diff] [blame] | 1473 |           if (!VDecl->hasExternalStorage()) | 
| Steve Naroff | 8745416 | 2009-04-13 17:58:46 +0000 | [diff] [blame] | 1474 |             Diag(VDecl->getLocation(), diag::err_objc_var_decl_inclass); | 
| Fariborz Jahanian | b31cb7f | 2009-03-21 18:06:45 +0000 | [diff] [blame] | 1475 |         } | 
| Chris Lattner | 682bf92 | 2009-03-29 16:50:03 +0000 | [diff] [blame] | 1476 |     } | 
| Fariborz Jahanian | 38e24c7 | 2009-03-18 22:33:24 +0000 | [diff] [blame] | 1477 |   } | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 1478 | } | 
 | 1479 |  | 
 | 1480 |  | 
 | 1481 | /// CvtQTToAstBitMask - utility routine to produce an AST bitmask for | 
 | 1482 | /// objective-c's type qualifier from the parser version of the same info. | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1483 | static Decl::ObjCDeclQualifier | 
| Ted Kremenek | a526c5c | 2008-01-07 19:49:32 +0000 | [diff] [blame] | 1484 | CvtQTToAstBitMask(ObjCDeclSpec::ObjCDeclQualifier PQTVal) { | 
 | 1485 |   Decl::ObjCDeclQualifier ret = Decl::OBJC_TQ_None; | 
 | 1486 |   if (PQTVal & ObjCDeclSpec::DQ_In) | 
 | 1487 |     ret = (Decl::ObjCDeclQualifier)(ret | Decl::OBJC_TQ_In); | 
 | 1488 |   if (PQTVal & ObjCDeclSpec::DQ_Inout) | 
 | 1489 |     ret = (Decl::ObjCDeclQualifier)(ret | Decl::OBJC_TQ_Inout); | 
 | 1490 |   if (PQTVal & ObjCDeclSpec::DQ_Out) | 
 | 1491 |     ret = (Decl::ObjCDeclQualifier)(ret | Decl::OBJC_TQ_Out); | 
 | 1492 |   if (PQTVal & ObjCDeclSpec::DQ_Bycopy) | 
 | 1493 |     ret = (Decl::ObjCDeclQualifier)(ret | Decl::OBJC_TQ_Bycopy); | 
 | 1494 |   if (PQTVal & ObjCDeclSpec::DQ_Byref) | 
 | 1495 |     ret = (Decl::ObjCDeclQualifier)(ret | Decl::OBJC_TQ_Byref); | 
 | 1496 |   if (PQTVal & ObjCDeclSpec::DQ_Oneway) | 
 | 1497 |     ret = (Decl::ObjCDeclQualifier)(ret | Decl::OBJC_TQ_Oneway); | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 1498 |  | 
 | 1499 |   return ret; | 
 | 1500 | } | 
 | 1501 |  | 
| Ted Kremenek | 422bae7 | 2010-04-18 04:59:38 +0000 | [diff] [blame] | 1502 | static inline | 
 | 1503 | bool containsInvalidMethodImplAttribute(const AttributeList *A) { | 
 | 1504 |   // The 'ibaction' attribute is allowed on method definitions because of | 
 | 1505 |   // how the IBAction macro is used on both method declarations and definitions. | 
 | 1506 |   // If the method definitions contains any other attributes, return true. | 
 | 1507 |   while (A && A->getKind() == AttributeList::AT_IBAction) | 
 | 1508 |     A = A->getNext(); | 
 | 1509 |   return A != NULL; | 
 | 1510 | } | 
 | 1511 |  | 
| Chris Lattner | b28317a | 2009-03-28 19:18:32 +0000 | [diff] [blame] | 1512 | Sema::DeclPtrTy Sema::ActOnMethodDeclaration( | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 1513 |     SourceLocation MethodLoc, SourceLocation EndLoc, | 
| Chris Lattner | b28317a | 2009-03-28 19:18:32 +0000 | [diff] [blame] | 1514 |     tok::TokenKind MethodType, DeclPtrTy classDecl, | 
| Ted Kremenek | a526c5c | 2008-01-07 19:49:32 +0000 | [diff] [blame] | 1515 |     ObjCDeclSpec &ReturnQT, TypeTy *ReturnType, | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 1516 |     Selector Sel, | 
 | 1517 |     // optional arguments. The number of types/arguments is obtained | 
 | 1518 |     // from the Sel.getNumArgs(). | 
| Chris Lattner | e294d3f | 2009-04-11 18:57:04 +0000 | [diff] [blame] | 1519 |     ObjCArgInfo *ArgInfo, | 
| Fariborz Jahanian | 4f4fd92 | 2010-04-08 00:30:06 +0000 | [diff] [blame] | 1520 |     DeclaratorChunk::ParamInfo *CParamInfo, unsigned CNumArgs, // c-style args | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 1521 |     AttributeList *AttrList, tok::ObjCKeywordKind MethodDeclKind, | 
 | 1522 |     bool isVariadic) { | 
| Chris Lattner | b28317a | 2009-03-28 19:18:32 +0000 | [diff] [blame] | 1523 |   Decl *ClassDecl = classDecl.getAs<Decl>(); | 
| Steve Naroff | da323ad | 2008-02-29 21:48:07 +0000 | [diff] [blame] | 1524 |  | 
 | 1525 |   // Make sure we can establish a context for the method. | 
 | 1526 |   if (!ClassDecl) { | 
 | 1527 |     Diag(MethodLoc, diag::error_missing_method_context); | 
| Douglas Gregor | 9ea9bdb | 2010-03-01 23:15:13 +0000 | [diff] [blame] | 1528 |     getLabelMap().clear(); | 
| Chris Lattner | b28317a | 2009-03-28 19:18:32 +0000 | [diff] [blame] | 1529 |     return DeclPtrTy(); | 
| Steve Naroff | da323ad | 2008-02-29 21:48:07 +0000 | [diff] [blame] | 1530 |   } | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 1531 |   QualType resultDeclType; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1532 |  | 
| Douglas Gregor | 4bc1cb6 | 2010-03-08 14:59:44 +0000 | [diff] [blame] | 1533 |   TypeSourceInfo *ResultTInfo = 0; | 
| Steve Naroff | ccef371 | 2009-02-20 22:59:16 +0000 | [diff] [blame] | 1534 |   if (ReturnType) { | 
| Douglas Gregor | 4bc1cb6 | 2010-03-08 14:59:44 +0000 | [diff] [blame] | 1535 |     resultDeclType = GetTypeFromParser(ReturnType, &ResultTInfo); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1536 |  | 
| Steve Naroff | ccef371 | 2009-02-20 22:59:16 +0000 | [diff] [blame] | 1537 |     // Methods cannot return interface types. All ObjC objects are | 
 | 1538 |     // passed by reference. | 
| John McCall | c12c5bb | 2010-05-15 11:32:37 +0000 | [diff] [blame] | 1539 |     if (resultDeclType->isObjCObjectType()) { | 
| Chris Lattner | 2dd979f | 2009-04-11 19:08:56 +0000 | [diff] [blame] | 1540 |       Diag(MethodLoc, diag::err_object_cannot_be_passed_returned_by_value) | 
 | 1541 |         << 0 << resultDeclType; | 
| Chris Lattner | b28317a | 2009-03-28 19:18:32 +0000 | [diff] [blame] | 1542 |       return DeclPtrTy(); | 
| Steve Naroff | ccef371 | 2009-02-20 22:59:16 +0000 | [diff] [blame] | 1543 |     } | 
 | 1544 |   } else // get the type for "id". | 
| Ted Kremenek | a526c5c | 2008-01-07 19:49:32 +0000 | [diff] [blame] | 1545 |     resultDeclType = Context.getObjCIdType(); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1546 |  | 
 | 1547 |   ObjCMethodDecl* ObjCMethod = | 
| Chris Lattner | 6c4ae5d | 2008-03-16 00:49:28 +0000 | [diff] [blame] | 1548 |     ObjCMethodDecl::Create(Context, MethodLoc, EndLoc, Sel, resultDeclType, | 
| Douglas Gregor | 4bc1cb6 | 2010-03-08 14:59:44 +0000 | [diff] [blame] | 1549 |                            ResultTInfo, | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1550 |                            cast<DeclContext>(ClassDecl), | 
| Chris Lattner | 6c4ae5d | 2008-03-16 00:49:28 +0000 | [diff] [blame] | 1551 |                            MethodType == tok::minus, isVariadic, | 
| Fariborz Jahanian | 4607034 | 2008-05-07 20:53:44 +0000 | [diff] [blame] | 1552 |                            false, | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1553 |                            MethodDeclKind == tok::objc_optional ? | 
 | 1554 |                            ObjCMethodDecl::Optional : | 
| Chris Lattner | 6c4ae5d | 2008-03-16 00:49:28 +0000 | [diff] [blame] | 1555 |                            ObjCMethodDecl::Required); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1556 |  | 
| Chris Lattner | 0ed844b | 2008-04-04 06:12:32 +0000 | [diff] [blame] | 1557 |   llvm::SmallVector<ParmVarDecl*, 16> Params; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1558 |  | 
| Chris Lattner | 7db638d | 2009-04-11 19:42:43 +0000 | [diff] [blame] | 1559 |   for (unsigned i = 0, e = Sel.getNumArgs(); i != e; ++i) { | 
| John McCall | 58e4677 | 2009-10-23 21:48:59 +0000 | [diff] [blame] | 1560 |     QualType ArgType; | 
| John McCall | a93c934 | 2009-12-07 02:54:59 +0000 | [diff] [blame] | 1561 |     TypeSourceInfo *DI; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1562 |  | 
| Chris Lattner | e294d3f | 2009-04-11 18:57:04 +0000 | [diff] [blame] | 1563 |     if (ArgInfo[i].Type == 0) { | 
| John McCall | 58e4677 | 2009-10-23 21:48:59 +0000 | [diff] [blame] | 1564 |       ArgType = Context.getObjCIdType(); | 
 | 1565 |       DI = 0; | 
| Chris Lattner | e294d3f | 2009-04-11 18:57:04 +0000 | [diff] [blame] | 1566 |     } else { | 
| John McCall | 58e4677 | 2009-10-23 21:48:59 +0000 | [diff] [blame] | 1567 |       ArgType = GetTypeFromParser(ArgInfo[i].Type, &DI); | 
| Steve Naroff | 6082c62 | 2008-12-09 19:36:17 +0000 | [diff] [blame] | 1568 |       // Perform the default array/function conversions (C99 6.7.5.3p[7,8]). | 
| Chris Lattner | f97e8fa | 2009-04-11 19:34:56 +0000 | [diff] [blame] | 1569 |       ArgType = adjustParameterType(ArgType); | 
| Chris Lattner | e294d3f | 2009-04-11 18:57:04 +0000 | [diff] [blame] | 1570 |     } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1571 |  | 
| John McCall | 58e4677 | 2009-10-23 21:48:59 +0000 | [diff] [blame] | 1572 |     ParmVarDecl* Param | 
 | 1573 |       = ParmVarDecl::Create(Context, ObjCMethod, ArgInfo[i].NameLoc, | 
 | 1574 |                             ArgInfo[i].Name, ArgType, DI, | 
| Douglas Gregor | 16573fa | 2010-04-19 22:54:31 +0000 | [diff] [blame] | 1575 |                             VarDecl::None, VarDecl::None, 0); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1576 |  | 
| John McCall | c12c5bb | 2010-05-15 11:32:37 +0000 | [diff] [blame] | 1577 |     if (ArgType->isObjCObjectType()) { | 
| Chris Lattner | f97e8fa | 2009-04-11 19:34:56 +0000 | [diff] [blame] | 1578 |       Diag(ArgInfo[i].NameLoc, | 
 | 1579 |            diag::err_object_cannot_be_passed_returned_by_value) | 
 | 1580 |         << 1 << ArgType; | 
 | 1581 |       Param->setInvalidDecl(); | 
 | 1582 |     } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1583 |  | 
| Chris Lattner | 0ed844b | 2008-04-04 06:12:32 +0000 | [diff] [blame] | 1584 |     Param->setObjCDeclQualifier( | 
| Chris Lattner | e294d3f | 2009-04-11 18:57:04 +0000 | [diff] [blame] | 1585 |       CvtQTToAstBitMask(ArgInfo[i].DeclSpec.getObjCDeclQualifier())); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1586 |  | 
| Chris Lattner | f97e8fa | 2009-04-11 19:34:56 +0000 | [diff] [blame] | 1587 |     // Apply the attributes to the parameter. | 
| Douglas Gregor | 9cdda0c | 2009-06-17 21:51:59 +0000 | [diff] [blame] | 1588 |     ProcessDeclAttributeList(TUScope, Param, ArgInfo[i].ArgAttrs); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1589 |  | 
| Chris Lattner | 0ed844b | 2008-04-04 06:12:32 +0000 | [diff] [blame] | 1590 |     Params.push_back(Param); | 
 | 1591 |   } | 
 | 1592 |  | 
| Fariborz Jahanian | 4f4fd92 | 2010-04-08 00:30:06 +0000 | [diff] [blame] | 1593 |   for (unsigned i = 0, e = CNumArgs; i != e; ++i) { | 
 | 1594 |     ParmVarDecl *Param = CParamInfo[i].Param.getAs<ParmVarDecl>(); | 
 | 1595 |     QualType ArgType = Param->getType(); | 
 | 1596 |     if (ArgType.isNull()) | 
 | 1597 |       ArgType = Context.getObjCIdType(); | 
 | 1598 |     else | 
 | 1599 |       // Perform the default array/function conversions (C99 6.7.5.3p[7,8]). | 
 | 1600 |       ArgType = adjustParameterType(ArgType); | 
| John McCall | c12c5bb | 2010-05-15 11:32:37 +0000 | [diff] [blame] | 1601 |     if (ArgType->isObjCObjectType()) { | 
| Fariborz Jahanian | 4f4fd92 | 2010-04-08 00:30:06 +0000 | [diff] [blame] | 1602 |       Diag(Param->getLocation(), | 
 | 1603 |            diag::err_object_cannot_be_passed_returned_by_value) | 
 | 1604 |       << 1 << ArgType; | 
 | 1605 |       Param->setInvalidDecl(); | 
 | 1606 |     } | 
 | 1607 |     Param->setDeclContext(ObjCMethod); | 
 | 1608 |     IdResolver.RemoveDecl(Param); | 
 | 1609 |     Params.push_back(Param); | 
 | 1610 |   } | 
 | 1611 |    | 
| Fariborz Jahanian | 4ecb25f | 2010-04-09 15:40:42 +0000 | [diff] [blame] | 1612 |   ObjCMethod->setMethodParams(Context, Params.data(), Params.size(), | 
 | 1613 |                               Sel.getNumArgs()); | 
| Ted Kremenek | a526c5c | 2008-01-07 19:49:32 +0000 | [diff] [blame] | 1614 |   ObjCMethod->setObjCDeclQualifier( | 
 | 1615 |     CvtQTToAstBitMask(ReturnQT.getObjCDeclQualifier())); | 
 | 1616 |   const ObjCMethodDecl *PrevMethod = 0; | 
| Daniel Dunbar | 3568249 | 2008-09-26 04:12:28 +0000 | [diff] [blame] | 1617 |  | 
 | 1618 |   if (AttrList) | 
| Douglas Gregor | 9cdda0c | 2009-06-17 21:51:59 +0000 | [diff] [blame] | 1619 |     ProcessDeclAttributeList(TUScope, ObjCMethod, AttrList); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1620 |  | 
| John McCall | 54abf7d | 2009-11-04 02:18:39 +0000 | [diff] [blame] | 1621 |   const ObjCMethodDecl *InterfaceMD = 0; | 
 | 1622 |  | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1623 |   // For implementations (which can be very "coarse grain"), we add the | 
 | 1624 |   // method now. This allows the AST to implement lookup methods that work | 
 | 1625 |   // incrementally (without waiting until we parse the @end). It also allows | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 1626 |   // us to flag multiple declaration errors as they occur. | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1627 |   if (ObjCImplementationDecl *ImpDecl = | 
| Chris Lattner | 6c4ae5d | 2008-03-16 00:49:28 +0000 | [diff] [blame] | 1628 |         dyn_cast<ObjCImplementationDecl>(ClassDecl)) { | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 1629 |     if (MethodType == tok::minus) { | 
| Argyrios Kyrtzidis | 17945a0 | 2009-06-30 02:36:12 +0000 | [diff] [blame] | 1630 |       PrevMethod = ImpDecl->getInstanceMethod(Sel); | 
 | 1631 |       ImpDecl->addInstanceMethod(ObjCMethod); | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 1632 |     } else { | 
| Argyrios Kyrtzidis | 17945a0 | 2009-06-30 02:36:12 +0000 | [diff] [blame] | 1633 |       PrevMethod = ImpDecl->getClassMethod(Sel); | 
 | 1634 |       ImpDecl->addClassMethod(ObjCMethod); | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 1635 |     } | 
| John McCall | 54abf7d | 2009-11-04 02:18:39 +0000 | [diff] [blame] | 1636 |     InterfaceMD = ImpDecl->getClassInterface()->getMethod(Sel, | 
 | 1637 |                                                    MethodType == tok::minus); | 
| Ted Kremenek | 422bae7 | 2010-04-18 04:59:38 +0000 | [diff] [blame] | 1638 |     if (containsInvalidMethodImplAttribute(AttrList)) | 
| Fariborz Jahanian | 5d36ac2 | 2009-05-12 21:36:23 +0000 | [diff] [blame] | 1639 |       Diag(EndLoc, diag::warn_attribute_method_def); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1640 |   } else if (ObjCCategoryImplDecl *CatImpDecl = | 
| Mike Stump | ac5fc7c | 2009-08-04 21:02:39 +0000 | [diff] [blame] | 1641 |              dyn_cast<ObjCCategoryImplDecl>(ClassDecl)) { | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 1642 |     if (MethodType == tok::minus) { | 
| Argyrios Kyrtzidis | 17945a0 | 2009-06-30 02:36:12 +0000 | [diff] [blame] | 1643 |       PrevMethod = CatImpDecl->getInstanceMethod(Sel); | 
 | 1644 |       CatImpDecl->addInstanceMethod(ObjCMethod); | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 1645 |     } else { | 
| Argyrios Kyrtzidis | 17945a0 | 2009-06-30 02:36:12 +0000 | [diff] [blame] | 1646 |       PrevMethod = CatImpDecl->getClassMethod(Sel); | 
 | 1647 |       CatImpDecl->addClassMethod(ObjCMethod); | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 1648 |     } | 
| Ted Kremenek | 422bae7 | 2010-04-18 04:59:38 +0000 | [diff] [blame] | 1649 |     if (containsInvalidMethodImplAttribute(AttrList)) | 
| Fariborz Jahanian | 5d36ac2 | 2009-05-12 21:36:23 +0000 | [diff] [blame] | 1650 |       Diag(EndLoc, diag::warn_attribute_method_def); | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 1651 |   } | 
 | 1652 |   if (PrevMethod) { | 
 | 1653 |     // You can never have two method definitions with the same name. | 
| Chris Lattner | 5f4a682 | 2008-11-23 23:12:31 +0000 | [diff] [blame] | 1654 |     Diag(ObjCMethod->getLocation(), diag::err_duplicate_method_decl) | 
| Chris Lattner | 077bf5e | 2008-11-24 03:33:13 +0000 | [diff] [blame] | 1655 |       << ObjCMethod->getDeclName(); | 
| Chris Lattner | 5f4a682 | 2008-11-23 23:12:31 +0000 | [diff] [blame] | 1656 |     Diag(PrevMethod->getLocation(), diag::note_previous_declaration); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1657 |   } | 
| John McCall | 54abf7d | 2009-11-04 02:18:39 +0000 | [diff] [blame] | 1658 |  | 
 | 1659 |   // If the interface declared this method, and it was deprecated there, | 
 | 1660 |   // mark it deprecated here. | 
 | 1661 |   if (InterfaceMD && InterfaceMD->hasAttr<DeprecatedAttr>()) | 
 | 1662 |     ObjCMethod->addAttr(::new (Context) DeprecatedAttr()); | 
 | 1663 |  | 
| Chris Lattner | b28317a | 2009-03-28 19:18:32 +0000 | [diff] [blame] | 1664 |   return DeclPtrTy::make(ObjCMethod); | 
| Chris Lattner | 4d39148 | 2007-12-12 07:09:47 +0000 | [diff] [blame] | 1665 | } | 
 | 1666 |  | 
| Chris Lattner | cc98eac | 2008-12-17 07:13:27 +0000 | [diff] [blame] | 1667 | bool Sema::CheckObjCDeclScope(Decl *D) { | 
| Douglas Gregor | ce35607 | 2009-01-06 23:51:29 +0000 | [diff] [blame] | 1668 |   if (isa<TranslationUnitDecl>(CurContext->getLookupContext())) | 
| Anders Carlsson | 1528145 | 2008-11-04 16:57:32 +0000 | [diff] [blame] | 1669 |     return false; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1670 |  | 
| Anders Carlsson | 1528145 | 2008-11-04 16:57:32 +0000 | [diff] [blame] | 1671 |   Diag(D->getLocation(), diag::err_objc_decls_may_only_appear_in_global_scope); | 
 | 1672 |   D->setInvalidDecl(); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1673 |  | 
| Anders Carlsson | 1528145 | 2008-11-04 16:57:32 +0000 | [diff] [blame] | 1674 |   return true; | 
 | 1675 | } | 
| Chris Lattner | cc98eac | 2008-12-17 07:13:27 +0000 | [diff] [blame] | 1676 |  | 
| Chris Lattner | cc98eac | 2008-12-17 07:13:27 +0000 | [diff] [blame] | 1677 | /// Called whenever @defs(ClassName) is encountered in the source.  Inserts the | 
 | 1678 | /// instance variables of ClassName into Decls. | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1679 | void Sema::ActOnDefs(Scope *S, DeclPtrTy TagD, SourceLocation DeclStart, | 
| Chris Lattner | cc98eac | 2008-12-17 07:13:27 +0000 | [diff] [blame] | 1680 |                      IdentifierInfo *ClassName, | 
| Chris Lattner | b28317a | 2009-03-28 19:18:32 +0000 | [diff] [blame] | 1681 |                      llvm::SmallVectorImpl<DeclPtrTy> &Decls) { | 
| Chris Lattner | cc98eac | 2008-12-17 07:13:27 +0000 | [diff] [blame] | 1682 |   // Check that ClassName is a valid class | 
| Douglas Gregor | c83c687 | 2010-04-15 22:33:43 +0000 | [diff] [blame] | 1683 |   ObjCInterfaceDecl *Class = getObjCInterfaceDecl(ClassName, DeclStart); | 
| Chris Lattner | cc98eac | 2008-12-17 07:13:27 +0000 | [diff] [blame] | 1684 |   if (!Class) { | 
 | 1685 |     Diag(DeclStart, diag::err_undef_interface) << ClassName; | 
 | 1686 |     return; | 
 | 1687 |   } | 
| Fariborz Jahanian | 0468fb9 | 2009-04-21 20:28:41 +0000 | [diff] [blame] | 1688 |   if (LangOpts.ObjCNonFragileABI) { | 
 | 1689 |     Diag(DeclStart, diag::err_atdef_nonfragile_interface); | 
 | 1690 |     return; | 
 | 1691 |   } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1692 |  | 
| Chris Lattner | cc98eac | 2008-12-17 07:13:27 +0000 | [diff] [blame] | 1693 |   // Collect the instance variables | 
| Fariborz Jahanian | 4183335 | 2009-06-04 17:08:55 +0000 | [diff] [blame] | 1694 |   llvm::SmallVector<FieldDecl*, 32> RecFields; | 
 | 1695 |   Context.CollectObjCIvars(Class, RecFields); | 
 | 1696 |   // For each ivar, create a fresh ObjCAtDefsFieldDecl. | 
 | 1697 |   for (unsigned i = 0; i < RecFields.size(); i++) { | 
 | 1698 |     FieldDecl* ID = RecFields[i]; | 
 | 1699 |     RecordDecl *Record = dyn_cast<RecordDecl>(TagD.getAs<Decl>()); | 
 | 1700 |     Decl *FD = ObjCAtDefsFieldDecl::Create(Context, Record, ID->getLocation(), | 
 | 1701 |                                            ID->getIdentifier(), ID->getType(), | 
 | 1702 |                                            ID->getBitWidth()); | 
 | 1703 |     Decls.push_back(Sema::DeclPtrTy::make(FD)); | 
 | 1704 |   } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1705 |  | 
| Chris Lattner | cc98eac | 2008-12-17 07:13:27 +0000 | [diff] [blame] | 1706 |   // Introduce all of these fields into the appropriate scope. | 
| Chris Lattner | b28317a | 2009-03-28 19:18:32 +0000 | [diff] [blame] | 1707 |   for (llvm::SmallVectorImpl<DeclPtrTy>::iterator D = Decls.begin(); | 
| Chris Lattner | cc98eac | 2008-12-17 07:13:27 +0000 | [diff] [blame] | 1708 |        D != Decls.end(); ++D) { | 
| Chris Lattner | b28317a | 2009-03-28 19:18:32 +0000 | [diff] [blame] | 1709 |     FieldDecl *FD = cast<FieldDecl>(D->getAs<Decl>()); | 
| Chris Lattner | cc98eac | 2008-12-17 07:13:27 +0000 | [diff] [blame] | 1710 |     if (getLangOptions().CPlusPlus) | 
 | 1711 |       PushOnScopeChains(cast<FieldDecl>(FD), S); | 
| Chris Lattner | b28317a | 2009-03-28 19:18:32 +0000 | [diff] [blame] | 1712 |     else if (RecordDecl *Record = dyn_cast<RecordDecl>(TagD.getAs<Decl>())) | 
| Argyrios Kyrtzidis | 17945a0 | 2009-06-30 02:36:12 +0000 | [diff] [blame] | 1713 |       Record->addDecl(FD); | 
| Chris Lattner | cc98eac | 2008-12-17 07:13:27 +0000 | [diff] [blame] | 1714 |   } | 
 | 1715 | } | 
 | 1716 |  | 
| Douglas Gregor | 160b563 | 2010-04-26 17:32:49 +0000 | [diff] [blame] | 1717 | /// \brief Build a type-check a new Objective-C exception variable declaration. | 
 | 1718 | VarDecl *Sema::BuildObjCExceptionDecl(TypeSourceInfo *TInfo,  | 
 | 1719 |                                       QualType T, | 
 | 1720 |                                       IdentifierInfo *Name,  | 
 | 1721 |                                       SourceLocation NameLoc, | 
 | 1722 |                                       bool Invalid) { | 
 | 1723 |   // ISO/IEC TR 18037 S6.7.3: "The type of an object with automatic storage  | 
 | 1724 |   // duration shall not be qualified by an address-space qualifier." | 
 | 1725 |   // Since all parameters have automatic store duration, they can not have | 
 | 1726 |   // an address space. | 
 | 1727 |   if (T.getAddressSpace() != 0) { | 
 | 1728 |     Diag(NameLoc, diag::err_arg_with_address_space); | 
 | 1729 |     Invalid = true; | 
 | 1730 |   } | 
 | 1731 |    | 
 | 1732 |   // An @catch parameter must be an unqualified object pointer type; | 
 | 1733 |   // FIXME: Recover from "NSObject foo" by inserting the * in "NSObject *foo"? | 
 | 1734 |   if (Invalid) { | 
 | 1735 |     // Don't do any further checking. | 
| Douglas Gregor | be270a0 | 2010-04-26 17:57:08 +0000 | [diff] [blame] | 1736 |   } else if (T->isDependentType()) { | 
 | 1737 |     // Okay: we don't know what this type will instantiate to. | 
| Douglas Gregor | 160b563 | 2010-04-26 17:32:49 +0000 | [diff] [blame] | 1738 |   } else if (!T->isObjCObjectPointerType()) { | 
 | 1739 |     Invalid = true; | 
 | 1740 |     Diag(NameLoc ,diag::err_catch_param_not_objc_type); | 
 | 1741 |   } else if (T->isObjCQualifiedIdType()) { | 
 | 1742 |     Invalid = true; | 
 | 1743 |     Diag(NameLoc, diag::err_illegal_qualifiers_on_catch_parm); | 
 | 1744 |   } | 
 | 1745 |    | 
 | 1746 |   VarDecl *New = VarDecl::Create(Context, CurContext, NameLoc, Name, T, TInfo, | 
| Douglas Gregor | 324b54d | 2010-05-03 18:51:14 +0000 | [diff] [blame] | 1747 |                                  VarDecl::None, VarDecl::None); | 
 | 1748 |   New->setExceptionVariable(true); | 
 | 1749 |    | 
| Douglas Gregor | 160b563 | 2010-04-26 17:32:49 +0000 | [diff] [blame] | 1750 |   if (Invalid) | 
 | 1751 |     New->setInvalidDecl(); | 
 | 1752 |   return New; | 
 | 1753 | } | 
 | 1754 |  | 
| Douglas Gregor | 4e6c0d1 | 2010-04-23 23:01:43 +0000 | [diff] [blame] | 1755 | Sema::DeclPtrTy Sema::ActOnObjCExceptionDecl(Scope *S, Declarator &D) { | 
| Douglas Gregor | 160b563 | 2010-04-26 17:32:49 +0000 | [diff] [blame] | 1756 |   const DeclSpec &DS = D.getDeclSpec(); | 
 | 1757 |    | 
 | 1758 |   // We allow the "register" storage class on exception variables because | 
 | 1759 |   // GCC did, but we drop it completely. Any other storage class is an error. | 
 | 1760 |   if (DS.getStorageClassSpec() == DeclSpec::SCS_register) { | 
 | 1761 |     Diag(DS.getStorageClassSpecLoc(), diag::warn_register_objc_catch_parm) | 
 | 1762 |       << FixItHint::CreateRemoval(SourceRange(DS.getStorageClassSpecLoc())); | 
 | 1763 |   } else if (DS.getStorageClassSpec() != DeclSpec::SCS_unspecified) { | 
 | 1764 |     Diag(DS.getStorageClassSpecLoc(), diag::err_storage_spec_on_catch_parm) | 
 | 1765 |       << DS.getStorageClassSpec(); | 
 | 1766 |   }   | 
 | 1767 |   if (D.getDeclSpec().isThreadSpecified()) | 
 | 1768 |     Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_invalid_thread); | 
 | 1769 |   D.getMutableDeclSpec().ClearStorageClassSpecs(); | 
 | 1770 |  | 
 | 1771 |   DiagnoseFunctionSpecifiers(D); | 
 | 1772 |    | 
 | 1773 |   // Check that there are no default arguments inside the type of this | 
 | 1774 |   // exception object (C++ only). | 
 | 1775 |   if (getLangOptions().CPlusPlus) | 
 | 1776 |     CheckExtraCXXDefaultArguments(D); | 
 | 1777 |    | 
| Douglas Gregor | 160b563 | 2010-04-26 17:32:49 +0000 | [diff] [blame] | 1778 |   TagDecl *OwnedDecl = 0; | 
| John McCall | bf1a028 | 2010-06-04 23:28:52 +0000 | [diff] [blame] | 1779 |   TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S, &OwnedDecl); | 
 | 1780 |   QualType ExceptionType = TInfo->getType(); | 
| Douglas Gregor | 160b563 | 2010-04-26 17:32:49 +0000 | [diff] [blame] | 1781 |    | 
 | 1782 |   if (getLangOptions().CPlusPlus && OwnedDecl && OwnedDecl->isDefinition()) { | 
 | 1783 |     // Objective-C++: Types shall not be defined in exception types. | 
 | 1784 |     Diag(OwnedDecl->getLocation(), diag::err_type_defined_in_param_type) | 
 | 1785 |       << Context.getTypeDeclType(OwnedDecl); | 
 | 1786 |   } | 
 | 1787 |  | 
 | 1788 |   VarDecl *New = BuildObjCExceptionDecl(TInfo, ExceptionType, D.getIdentifier(),  | 
 | 1789 |                                         D.getIdentifierLoc(),  | 
 | 1790 |                                         D.isInvalidType()); | 
 | 1791 |    | 
 | 1792 |   // Parameter declarators cannot be qualified (C++ [dcl.meaning]p1). | 
 | 1793 |   if (D.getCXXScopeSpec().isSet()) { | 
 | 1794 |     Diag(D.getIdentifierLoc(), diag::err_qualified_objc_catch_parm) | 
 | 1795 |       << D.getCXXScopeSpec().getRange(); | 
 | 1796 |     New->setInvalidDecl(); | 
 | 1797 |   } | 
 | 1798 |    | 
 | 1799 |   // Add the parameter declaration into this scope. | 
 | 1800 |   S->AddDecl(DeclPtrTy::make(New)); | 
 | 1801 |   if (D.getIdentifier()) | 
 | 1802 |     IdResolver.AddDecl(New); | 
 | 1803 |    | 
 | 1804 |   ProcessDeclAttributes(S, New, D); | 
 | 1805 |    | 
 | 1806 |   if (New->hasAttr<BlocksAttr>()) | 
 | 1807 |     Diag(New->getLocation(), diag::err_block_on_nonlocal); | 
 | 1808 |   return DeclPtrTy::make(New); | 
| Douglas Gregor | 4e6c0d1 | 2010-04-23 23:01:43 +0000 | [diff] [blame] | 1809 | } | 
| Fariborz Jahanian | 786cd15 | 2010-04-27 17:18:58 +0000 | [diff] [blame] | 1810 |  | 
 | 1811 | /// CollectIvarsToConstructOrDestruct - Collect those ivars which require | 
| Fariborz Jahanian | e4498c6 | 2010-04-28 16:11:27 +0000 | [diff] [blame] | 1812 | /// initialization. | 
| Fariborz Jahanian | 786cd15 | 2010-04-27 17:18:58 +0000 | [diff] [blame] | 1813 | void Sema::CollectIvarsToConstructOrDestruct(const ObjCInterfaceDecl *OI, | 
| Fariborz Jahanian | e4498c6 | 2010-04-28 16:11:27 +0000 | [diff] [blame] | 1814 |                                 llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars) { | 
| Fariborz Jahanian | 786cd15 | 2010-04-27 17:18:58 +0000 | [diff] [blame] | 1815 |   for (ObjCInterfaceDecl::ivar_iterator I = OI->ivar_begin(), | 
 | 1816 |        E = OI->ivar_end(); I != E; ++I) { | 
 | 1817 |     ObjCIvarDecl *Iv = (*I); | 
 | 1818 |     QualType QT = Context.getBaseElementType(Iv->getType()); | 
| Douglas Gregor | 68dd3ee | 2010-05-20 02:24:22 +0000 | [diff] [blame] | 1819 |     if (QT->isRecordType()) | 
| Fariborz Jahanian | e4498c6 | 2010-04-28 16:11:27 +0000 | [diff] [blame] | 1820 |       Ivars.push_back(*I); | 
| Fariborz Jahanian | 786cd15 | 2010-04-27 17:18:58 +0000 | [diff] [blame] | 1821 |   } | 
 | 1822 |    | 
 | 1823 |   // Find ivars to construct/destruct in class extension. | 
 | 1824 |   if (const ObjCCategoryDecl *CDecl = OI->getClassExtension()) { | 
 | 1825 |     for (ObjCCategoryDecl::ivar_iterator I = CDecl->ivar_begin(), | 
 | 1826 |          E = CDecl->ivar_end(); I != E; ++I) { | 
 | 1827 |       ObjCIvarDecl *Iv = (*I); | 
 | 1828 |       QualType QT = Context.getBaseElementType(Iv->getType()); | 
| Douglas Gregor | 68dd3ee | 2010-05-20 02:24:22 +0000 | [diff] [blame] | 1829 |       if (QT->isRecordType()) | 
| Fariborz Jahanian | e4498c6 | 2010-04-28 16:11:27 +0000 | [diff] [blame] | 1830 |         Ivars.push_back(*I); | 
| Fariborz Jahanian | 786cd15 | 2010-04-27 17:18:58 +0000 | [diff] [blame] | 1831 |     } | 
 | 1832 |   } | 
 | 1833 |    | 
 | 1834 |   // Also add any ivar defined in this class's implementation.  This | 
 | 1835 |   // includes synthesized ivars. | 
 | 1836 |   if (ObjCImplementationDecl *ImplDecl = OI->getImplementation()) { | 
 | 1837 |     for (ObjCImplementationDecl::ivar_iterator I = ImplDecl->ivar_begin(), | 
 | 1838 |          E = ImplDecl->ivar_end(); I != E; ++I) { | 
 | 1839 |       ObjCIvarDecl *Iv = (*I); | 
 | 1840 |       QualType QT = Context.getBaseElementType(Iv->getType()); | 
| Douglas Gregor | 68dd3ee | 2010-05-20 02:24:22 +0000 | [diff] [blame] | 1841 |       if (QT->isRecordType()) | 
| Fariborz Jahanian | e4498c6 | 2010-04-28 16:11:27 +0000 | [diff] [blame] | 1842 |         Ivars.push_back(*I); | 
| Fariborz Jahanian | 786cd15 | 2010-04-27 17:18:58 +0000 | [diff] [blame] | 1843 |     } | 
 | 1844 |   } | 
 | 1845 | } | 
| Fariborz Jahanian | e4498c6 | 2010-04-28 16:11:27 +0000 | [diff] [blame] | 1846 |  | 
 | 1847 | void ObjCImplementationDecl::setIvarInitializers(ASTContext &C, | 
 | 1848 |                                     CXXBaseOrMemberInitializer ** initializers, | 
 | 1849 |                                                  unsigned numInitializers) { | 
 | 1850 |   if (numInitializers > 0) { | 
 | 1851 |     NumIvarInitializers = numInitializers; | 
 | 1852 |     CXXBaseOrMemberInitializer **ivarInitializers = | 
 | 1853 |     new (C) CXXBaseOrMemberInitializer*[NumIvarInitializers]; | 
 | 1854 |     memcpy(ivarInitializers, initializers, | 
 | 1855 |            numInitializers * sizeof(CXXBaseOrMemberInitializer*)); | 
 | 1856 |     IvarInitializers = ivarInitializers; | 
 | 1857 |   } | 
 | 1858 | } | 
 | 1859 |  |