diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp | 408 |
1 files changed, 321 insertions, 87 deletions
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp index f33e7bc..f44fb32 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp @@ -324,15 +324,15 @@ void Sema::ActOnStartOfObjCMethodDef(Scope *FnBodyScope, Decl *D) { PushOnScopeChains(MDecl->getSelfDecl(), FnBodyScope); PushOnScopeChains(MDecl->getCmdDecl(), FnBodyScope); + // The ObjC parser requires parameter names so there's no need to check. + CheckParmsForFunctionDef(MDecl->param_begin(), MDecl->param_end(), + /*CheckParameterNames=*/false); + // Introduce all of the other parameters into this scope. for (ObjCMethodDecl::param_iterator PI = MDecl->param_begin(), E = MDecl->param_end(); PI != E; ++PI) { ParmVarDecl *Param = (*PI); if (!Param->isInvalidDecl() && - RequireCompleteType(Param->getLocation(), Param->getType(), - diag::err_typecheck_decl_incomplete_type)) - Param->setInvalidDecl(); - if (!Param->isInvalidDecl() && getLangOpts().ObjCAutoRefCount && !HasExplicitOwnershipAttr(*this, Param)) Diag(Param->getLocation(), diag::warn_arc_strong_pointer_objc_pointer) << @@ -350,7 +350,7 @@ void Sema::ActOnStartOfObjCMethodDef(Scope *FnBodyScope, Decl *D) { case OMF_release: case OMF_autorelease: Diag(MDecl->getLocation(), diag::err_arc_illegal_method_def) - << MDecl->getSelector(); + << 0 << MDecl->getSelector(); break; case OMF_None: @@ -459,6 +459,23 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc, // Create a declaration to describe this @interface. ObjCInterfaceDecl* PrevIDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl); + + if (PrevIDecl && PrevIDecl->getIdentifier() != ClassName) { + // A previous decl with a different name is because of + // @compatibility_alias, for example: + // \code + // @class NewImage; + // @compatibility_alias OldImage NewImage; + // \endcode + // A lookup for 'OldImage' will return the 'NewImage' decl. + // + // In such a case use the real declaration name, instead of the alias one, + // otherwise we will break IdentifierResolver and redecls-chain invariants. + // FIXME: If necessary, add a bit to indicate that this ObjCInterfaceDecl + // has been aliased. + ClassName = PrevIDecl->getIdentifier(); + } + ObjCInterfaceDecl *IDecl = ObjCInterfaceDecl::Create(Context, CurContext, AtInterfaceLoc, ClassName, PrevIDecl, ClassLoc); @@ -494,11 +511,9 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc, if (TypoCorrection Corrected = CorrectTypo( DeclarationNameInfo(SuperName, SuperLoc), LookupOrdinaryName, TUScope, NULL, Validator)) { + diagnoseTypo(Corrected, PDiag(diag::err_undef_superclass_suggest) + << SuperName << ClassName); PrevDecl = Corrected.getCorrectionDeclAs<ObjCInterfaceDecl>(); - Diag(SuperLoc, diag::err_undef_superclass_suggest) - << SuperName << ClassName << PrevDecl->getDeclName(); - Diag(PrevDecl->getLocation(), diag::note_previous_decl) - << PrevDecl->getDeclName(); } } @@ -575,6 +590,29 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc, return ActOnObjCContainerStartDefinition(IDecl); } +/// ActOnTypedefedProtocols - this action finds protocol list as part of the +/// typedef'ed use for a qualified super class and adds them to the list +/// of the protocols. +void Sema::ActOnTypedefedProtocols(SmallVectorImpl<Decl *> &ProtocolRefs, + IdentifierInfo *SuperName, + SourceLocation SuperLoc) { + if (!SuperName) + return; + NamedDecl* IDecl = LookupSingleName(TUScope, SuperName, SuperLoc, + LookupOrdinaryName); + if (!IDecl) + return; + + if (const TypedefNameDecl *TDecl = dyn_cast_or_null<TypedefNameDecl>(IDecl)) { + QualType T = TDecl->getUnderlyingType(); + if (T->isObjCObjectType()) + if (const ObjCObjectType *OPT = T->getAs<ObjCObjectType>()) + for (ObjCObjectType::qual_iterator I = OPT->qual_begin(), + E = OPT->qual_end(); I != E; ++I) + ProtocolRefs.push_back(*I); + } +} + /// ActOnCompatibilityAlias - this action is called after complete parsing of /// a \@compatibility_alias declaration. It sets up the alias relationships. Decl *Sema::ActOnCompatibilityAlias(SourceLocation AtLoc, @@ -586,10 +624,7 @@ Decl *Sema::ActOnCompatibilityAlias(SourceLocation AtLoc, NamedDecl *ADecl = LookupSingleName(TUScope, AliasName, AliasLocation, LookupOrdinaryName, ForRedeclaration); if (ADecl) { - if (isa<ObjCCompatibleAliasDecl>(ADecl)) - Diag(AliasLocation, diag::warn_previous_alias_decl); - else - Diag(AliasLocation, diag::err_conflicting_aliasing_type) << AliasName; + Diag(AliasLocation, diag::err_conflicting_aliasing_type) << AliasName; Diag(ADecl->getLocation(), diag::note_previous_declaration); return 0; } @@ -732,12 +767,9 @@ Sema::FindProtocolDeclaration(bool WarnOnDeclarations, TypoCorrection Corrected = CorrectTypo( DeclarationNameInfo(ProtocolId[i].first, ProtocolId[i].second), LookupObjCProtocolName, TUScope, NULL, Validator); - if ((PDecl = Corrected.getCorrectionDeclAs<ObjCProtocolDecl>())) { - Diag(ProtocolId[i].second, diag::err_undeclared_protocol_suggest) - << ProtocolId[i].first << Corrected.getCorrection(); - Diag(PDecl->getLocation(), diag::note_previous_decl) - << PDecl->getDeclName(); - } + if ((PDecl = Corrected.getCorrectionDeclAs<ObjCProtocolDecl>())) + diagnoseTypo(Corrected, PDiag(diag::err_undeclared_protocol_suggest) + << ProtocolId[i].first); } if (!PDecl) { @@ -819,7 +851,7 @@ Sema::ActOnForwardProtocolDeclaration(SourceLocation AtProtocolLoc, DeclsInGroup.push_back(PDecl); } - return BuildDeclaratorGroup(DeclsInGroup.data(), DeclsInGroup.size(), false); + return BuildDeclaratorGroup(DeclsInGroup, false); } Decl *Sema:: @@ -935,6 +967,7 @@ Decl *Sema::ActOnStartCategoryImplementation( << CatName; Diag(CatIDecl->getImplementation()->getLocation(), diag::note_previous_definition); + CDecl->setInvalidDecl(); } else { CatIDecl->setImplementation(CDecl); // Warn on implementating category of deprecated class under @@ -954,7 +987,7 @@ Decl *Sema::ActOnStartClassImplementation( IdentifierInfo *ClassName, SourceLocation ClassLoc, IdentifierInfo *SuperClassname, SourceLocation SuperClassLoc) { - ObjCInterfaceDecl* IDecl = 0; + ObjCInterfaceDecl *IDecl = 0; // Check for another declaration kind with the same name. NamedDecl *PrevDecl = LookupSingleName(TUScope, ClassName, ClassLoc, LookupOrdinaryName, @@ -966,24 +999,19 @@ Decl *Sema::ActOnStartClassImplementation( RequireCompleteType(ClassLoc, Context.getObjCInterfaceType(IDecl), diag::warn_undef_interface); } else { - // We did not find anything with the name ClassName; try to correct for + // We did not find anything with the name ClassName; try to correct for // typos in the class name. ObjCInterfaceValidatorCCC Validator; - if (TypoCorrection Corrected = CorrectTypo( - DeclarationNameInfo(ClassName, ClassLoc), LookupOrdinaryName, TUScope, - NULL, Validator)) { - // Suggest the (potentially) correct interface name. However, put the - // fix-it hint itself in a separate note, since changing the name in - // the warning would make the fix-it change semantics.However, don't - // provide a code-modification hint or use the typo name for recovery, - // because this is just a warning. The program may actually be correct. - IDecl = Corrected.getCorrectionDeclAs<ObjCInterfaceDecl>(); - DeclarationName CorrectedName = Corrected.getCorrection(); - Diag(ClassLoc, diag::warn_undef_interface_suggest) - << ClassName << CorrectedName; - Diag(IDecl->getLocation(), diag::note_previous_decl) << CorrectedName - << FixItHint::CreateReplacement(ClassLoc, CorrectedName.getAsString()); - IDecl = 0; + TypoCorrection Corrected = + CorrectTypo(DeclarationNameInfo(ClassName, ClassLoc), + LookupOrdinaryName, TUScope, NULL, Validator); + if (Corrected.getCorrectionDeclAs<ObjCInterfaceDecl>()) { + // Suggest the (potentially) correct interface name. Don't provide a + // code-modification hint or use the typo name for recovery, because + // this is just a warning. The program may actually be correct. + diagnoseTypo(Corrected, + PDiag(diag::warn_undef_interface_suggest) << ClassName, + /*ErrorRecovery*/false); } else { Diag(ClassLoc, diag::warn_undef_interface) << ClassName; } @@ -1056,6 +1084,7 @@ Decl *Sema::ActOnStartClassImplementation( Diag(ClassLoc, diag::err_dup_implementation_class) << ClassName; Diag(IDecl->getImplementation()->getLocation(), diag::note_previous_definition); + IMPDecl->setInvalidDecl(); } else { // add it to the list. IDecl->setImplementation(IMPDecl); PushOnScopeChains(IMPDecl, TUScope); @@ -1084,7 +1113,7 @@ Sema::ActOnFinishObjCImplementation(Decl *ObjCImpDecl, ArrayRef<Decl *> Decls) { DeclsInGroup.push_back(ObjCImpDecl); - return BuildDeclaratorGroup(DeclsInGroup.data(), DeclsInGroup.size(), false); + return BuildDeclaratorGroup(DeclsInGroup, false); } void Sema::CheckImplementationIvars(ObjCImplementationDecl *ImpDecl, @@ -1124,6 +1153,19 @@ void Sema::CheckImplementationIvars(ObjCImplementationDecl *ImpDecl, Diag(ClsIvar->getLocation(), diag::note_previous_definition); continue; } + // Check class extensions (unnamed categories) for duplicate ivars. + for (ObjCInterfaceDecl::visible_extensions_iterator + Ext = IDecl->visible_extensions_begin(), + ExtEnd = IDecl->visible_extensions_end(); + Ext != ExtEnd; ++Ext) { + ObjCCategoryDecl *CDecl = *Ext; + if (const ObjCIvarDecl *ClsExtIvar = + CDecl->getIvarDecl(ImplIvar->getIdentifier())) { + Diag(ImplIvar->getLocation(), diag::err_duplicate_ivar_declaration); + Diag(ClsExtIvar->getLocation(), diag::note_previous_definition); + continue; + } + } // Instance ivar to Implementation's DeclContext. ImplIvar->setLexicalDeclContext(ImpDecl); IDecl->makeDeclVisibleInContext(ImplIvar); @@ -1469,8 +1511,8 @@ static bool checkMethodFamilyMismatch(Sema &S, ObjCMethodDecl *impl, reasonSelector = R_NonObjectReturn; } - S.Diag(impl->getLocation(), errorID) << familySelector << reasonSelector; - S.Diag(decl->getLocation(), noteID) << familySelector << reasonSelector; + S.Diag(impl->getLocation(), errorID) << int(familySelector) << int(reasonSelector); + S.Diag(decl->getLocation(), noteID) << int(familySelector) << int(reasonSelector); return true; } @@ -1689,9 +1731,8 @@ void Sema::MatchAllMethodDeclarations(const SelectorSet &InsMap, // implemented in the implementation class. If so, their types match. for (ObjCInterfaceDecl::instmeth_iterator I = CDecl->instmeth_begin(), E = CDecl->instmeth_end(); I != E; ++I) { - if (InsMapSeen.count((*I)->getSelector())) - continue; - InsMapSeen.insert((*I)->getSelector()); + if (!InsMapSeen.insert((*I)->getSelector())) + continue; if (!(*I)->isPropertyAccessor() && !InsMap.count((*I)->getSelector())) { if (ImmediateClass) @@ -1718,11 +1759,11 @@ void Sema::MatchAllMethodDeclarations(const SelectorSet &InsMap, // Check and see if class methods in class interface have been // implemented in the implementation class. If so, their types match. - for (ObjCInterfaceDecl::classmeth_iterator - I = CDecl->classmeth_begin(), E = CDecl->classmeth_end(); I != E; ++I) { - if (ClsMapSeen.count((*I)->getSelector())) - continue; - ClsMapSeen.insert((*I)->getSelector()); + for (ObjCInterfaceDecl::classmeth_iterator I = CDecl->classmeth_begin(), + E = CDecl->classmeth_end(); + I != E; ++I) { + if (!ClsMapSeen.insert((*I)->getSelector())) + continue; if (!ClsMap.count((*I)->getSelector())) { if (ImmediateClass) WarnUndefinedMethod(IMPDecl->getLocation(), *I, IncompleteImpl, @@ -1742,6 +1783,16 @@ void Sema::MatchAllMethodDeclarations(const SelectorSet &InsMap, } } + if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl> (CDecl)) { + // Also, check for methods declared in protocols inherited by + // this protocol. + for (ObjCProtocolDecl::protocol_iterator + PI = PD->protocol_begin(), E = PD->protocol_end(); PI != E; ++PI) + MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen, + IMPDecl, (*PI), IncompleteImpl, false, + WarnCategoryMethodImpl); + } + if (ObjCInterfaceDecl *I = dyn_cast<ObjCInterfaceDecl> (CDecl)) { // when checking that methods in implementation match their declaration, // i.e. when WarnCategoryMethodImpl is false, check declarations in class @@ -1901,13 +1952,6 @@ Sema::ActOnForwardClassDeclaration(SourceLocation AtClassLoc, NamedDecl *PrevDecl = LookupSingleName(TUScope, IdentList[i], IdentLocs[i], LookupOrdinaryName, ForRedeclaration); - if (PrevDecl && PrevDecl->isTemplateParameter()) { - // Maybe we will complain about the shadowed template parameter. - DiagnoseTemplateParameterShadow(AtClassLoc, PrevDecl); - // Just pretend that we didn't see the previous declaration. - PrevDecl = 0; - } - if (PrevDecl && !isa<ObjCInterfaceDecl>(PrevDecl)) { // GCC apparently allows the following idiom: // @@ -1936,17 +1980,35 @@ Sema::ActOnForwardClassDeclaration(SourceLocation AtClassLoc, // Create a declaration to describe this forward declaration. ObjCInterfaceDecl *PrevIDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl); + + IdentifierInfo *ClassName = IdentList[i]; + if (PrevIDecl && PrevIDecl->getIdentifier() != ClassName) { + // A previous decl with a different name is because of + // @compatibility_alias, for example: + // \code + // @class NewImage; + // @compatibility_alias OldImage NewImage; + // \endcode + // A lookup for 'OldImage' will return the 'NewImage' decl. + // + // In such a case use the real declaration name, instead of the alias one, + // otherwise we will break IdentifierResolver and redecls-chain invariants. + // FIXME: If necessary, add a bit to indicate that this ObjCInterfaceDecl + // has been aliased. + ClassName = PrevIDecl->getIdentifier(); + } + ObjCInterfaceDecl *IDecl = ObjCInterfaceDecl::Create(Context, CurContext, AtClassLoc, - IdentList[i], PrevIDecl, IdentLocs[i]); + ClassName, PrevIDecl, IdentLocs[i]); IDecl->setAtEndRange(IdentLocs[i]); PushOnScopeChains(IDecl, TUScope); CheckObjCDeclScope(IDecl); DeclsInGroup.push_back(IDecl); } - - return BuildDeclaratorGroup(DeclsInGroup.data(), DeclsInGroup.size(), false); + + return BuildDeclaratorGroup(DeclsInGroup, false); } static bool tryMatchRecordTypes(ASTContext &Context, @@ -2093,6 +2155,10 @@ void Sema::addMethodToGlobalList(ObjCMethodList *List, ObjCMethodDecl *Method) { // signature. ObjCMethodList *Previous = List; for (; List; Previous = List, List = List->getNext()) { + // If we are building a module, keep all of the methods. + if (getLangOpts().Modules && !getLangOpts().CurrentModule.empty()) + continue; + if (!MatchTwoMethodDeclarations(Method, List->Method)) continue; @@ -2182,7 +2248,7 @@ ObjCMethodDecl *Sema::LookupMethodInGlobalPool(Selector Sel, SourceRange R, // Gather the non-hidden methods. ObjCMethodList &MethList = instance ? Pos->second.first : Pos->second.second; - llvm::SmallVector<ObjCMethodDecl *, 4> Methods; + SmallVector<ObjCMethodDecl *, 4> Methods; for (ObjCMethodList *M = &MethList; M; M = M->getNext()) { if (M->Method && !M->Method->isHidden()) { // If we're not supposed to warn about mismatches, we're done. @@ -2269,7 +2335,140 @@ ObjCMethodDecl *Sema::LookupImplementedMethodInGlobalPool(Selector Sel) { return 0; } -/// DiagnoseDuplicateIvars - +static void +HelperSelectorsForTypoCorrection( + SmallVectorImpl<const ObjCMethodDecl *> &BestMethod, + StringRef Typo, const ObjCMethodDecl * Method) { + const unsigned MaxEditDistance = 1; + unsigned BestEditDistance = MaxEditDistance + 1; + std::string MethodName = Method->getSelector().getAsString(); + + unsigned MinPossibleEditDistance = abs((int)MethodName.size() - (int)Typo.size()); + if (MinPossibleEditDistance > 0 && + Typo.size() / MinPossibleEditDistance < 1) + return; + unsigned EditDistance = Typo.edit_distance(MethodName, true, MaxEditDistance); + if (EditDistance > MaxEditDistance) + return; + if (EditDistance == BestEditDistance) + BestMethod.push_back(Method); + else if (EditDistance < BestEditDistance) { + BestMethod.clear(); + BestMethod.push_back(Method); + } +} + +static bool HelperIsMethodInObjCType(Sema &S, Selector Sel, + QualType ObjectType) { + if (ObjectType.isNull()) + return true; + if (S.LookupMethodInObjectType(Sel, ObjectType, true/*Instance method*/)) + return true; + return S.LookupMethodInObjectType(Sel, ObjectType, false/*Class method*/) != 0; +} + +const ObjCMethodDecl * +Sema::SelectorsForTypoCorrection(Selector Sel, + QualType ObjectType) { + unsigned NumArgs = Sel.getNumArgs(); + SmallVector<const ObjCMethodDecl *, 8> Methods; + bool ObjectIsId = true, ObjectIsClass = true; + if (ObjectType.isNull()) + ObjectIsId = ObjectIsClass = false; + else if (!ObjectType->isObjCObjectPointerType()) + return 0; + else if (const ObjCObjectPointerType *ObjCPtr = + ObjectType->getAsObjCInterfacePointerType()) { + ObjectType = QualType(ObjCPtr->getInterfaceType(), 0); + ObjectIsId = ObjectIsClass = false; + } + else if (ObjectType->isObjCIdType() || ObjectType->isObjCQualifiedIdType()) + ObjectIsClass = false; + else if (ObjectType->isObjCClassType() || ObjectType->isObjCQualifiedClassType()) + ObjectIsId = false; + else + return 0; + + for (GlobalMethodPool::iterator b = MethodPool.begin(), + e = MethodPool.end(); b != e; b++) { + // instance methods + for (ObjCMethodList *M = &b->second.first; M; M=M->getNext()) + if (M->Method && + (M->Method->getSelector().getNumArgs() == NumArgs) && + (M->Method->getSelector() != Sel)) { + if (ObjectIsId) + Methods.push_back(M->Method); + else if (!ObjectIsClass && + HelperIsMethodInObjCType(*this, M->Method->getSelector(), ObjectType)) + Methods.push_back(M->Method); + } + // class methods + for (ObjCMethodList *M = &b->second.second; M; M=M->getNext()) + if (M->Method && + (M->Method->getSelector().getNumArgs() == NumArgs) && + (M->Method->getSelector() != Sel)) { + if (ObjectIsClass) + Methods.push_back(M->Method); + else if (!ObjectIsId && + HelperIsMethodInObjCType(*this, M->Method->getSelector(), ObjectType)) + Methods.push_back(M->Method); + } + } + + SmallVector<const ObjCMethodDecl *, 8> SelectedMethods; + for (unsigned i = 0, e = Methods.size(); i < e; i++) { + HelperSelectorsForTypoCorrection(SelectedMethods, + Sel.getAsString(), Methods[i]); + } + return (SelectedMethods.size() == 1) ? SelectedMethods[0] : NULL; +} + +static void +HelperToDiagnoseMismatchedMethodsInGlobalPool(Sema &S, + ObjCMethodList &MethList) { + ObjCMethodList *M = &MethList; + ObjCMethodDecl *TargetMethod = M->Method; + while (TargetMethod && + isa<ObjCImplDecl>(TargetMethod->getDeclContext())) { + M = M->getNext(); + TargetMethod = M ? M->Method : 0; + } + if (!TargetMethod) + return; + bool FirstTime = true; + for (M = M->getNext(); M; M=M->getNext()) { + ObjCMethodDecl *MatchingMethodDecl = M->Method; + if (isa<ObjCImplDecl>(MatchingMethodDecl->getDeclContext())) + continue; + if (!S.MatchTwoMethodDeclarations(TargetMethod, + MatchingMethodDecl, Sema::MMS_loose)) { + if (FirstTime) { + FirstTime = false; + S.Diag(TargetMethod->getLocation(), diag::warning_multiple_selectors) + << TargetMethod->getSelector(); + } + S.Diag(MatchingMethodDecl->getLocation(), diag::note_also_found); + } + } +} + +void Sema::DiagnoseMismatchedMethodsInGlobalPool() { + unsigned DIAG = diag::warning_multiple_selectors; + if (Diags.getDiagnosticLevel(DIAG, SourceLocation()) + == DiagnosticsEngine::Ignored) + return; + for (GlobalMethodPool::iterator b = MethodPool.begin(), + e = MethodPool.end(); b != e; b++) { + // first, instance methods + ObjCMethodList &InstMethList = b->second.first; + HelperToDiagnoseMismatchedMethodsInGlobalPool(*this, InstMethList); + // second, class methods + ObjCMethodList &ClsMethList = b->second.second; + HelperToDiagnoseMismatchedMethodsInGlobalPool(*this, ClsMethList); + } +} + +/// DiagnoseDuplicateIvars - /// Check for duplicate ivars in the entire class at the start of /// \@implementation. This becomes necesssary because class extension can /// add ivars to a class in random order which will not be known until @@ -2313,13 +2512,9 @@ Sema::ObjCContainerKind Sema::getObjCContainerKind() const { } } -// Note: For class/category implemenations, allMethods/allProperties is -// always null. -Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, - Decl **allMethods, unsigned allNum, - Decl **allProperties, unsigned pNum, - DeclGroupPtrTy *allTUVars, unsigned tuvNum) { - +// Note: For class/category implementations, allMethods is always null. +Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, ArrayRef<Decl *> allMethods, + ArrayRef<DeclGroupPtrTy> allTUVars) { if (getObjCContainerKind() == Sema::OCK_None) return 0; @@ -2337,7 +2532,7 @@ Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, llvm::DenseMap<Selector, const ObjCMethodDecl*> InsMap; llvm::DenseMap<Selector, const ObjCMethodDecl*> ClsMap; - for (unsigned i = 0; i < allNum; i++ ) { + for (unsigned i = 0, e = allMethods.size(); i != e; i++ ) { ObjCMethodDecl *Method = cast_or_null<ObjCMethodDecl>(allMethods[i]); @@ -2504,8 +2699,8 @@ Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, } if (isInterfaceDeclKind) { // Reject invalid vardecls. - for (unsigned i = 0; i != tuvNum; i++) { - DeclGroupRef DG = allTUVars[i].getAsVal<DeclGroupRef>(); + for (unsigned i = 0, e = allTUVars.size(); i != e; i++) { + DeclGroupRef DG = allTUVars[i].get(); for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) if (VarDecl *VDecl = dyn_cast<VarDecl>(*I)) { if (!VDecl->hasExternalStorage()) @@ -2515,8 +2710,8 @@ Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, } ActOnObjCContainerFinishDefinition(); - for (unsigned i = 0; i != tuvNum; i++) { - DeclGroupRef DG = allTUVars[i].getAsVal<DeclGroupRef>(); + for (unsigned i = 0, e = allTUVars.size(); i != e; i++) { + DeclGroupRef DG = allTUVars[i].get(); for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) (*I)->setTopLevelDeclInObjCContainer(); Consumer.HandleTopLevelDeclInObjCContainer(DG); @@ -2911,14 +3106,9 @@ Decl *Sema::ActOnMethodDeclaration( if (ReturnType) { resultDeclType = GetTypeFromParser(ReturnType, &ResultTInfo); - // Methods cannot return interface types. All ObjC objects are - // passed by reference. - if (resultDeclType->isObjCObjectType()) { - Diag(MethodLoc, diag::err_object_cannot_be_passed_returned_by_value) - << 0 << resultDeclType; + if (CheckFunctionReturnType(resultDeclType, MethodLoc)) return 0; - } - + HasRelatedResultType = (resultDeclType == Context.getObjCInstanceType()); } else { // get the type for "id". resultDeclType = Context.getObjCIdType(); @@ -2945,7 +3135,7 @@ Decl *Sema::ActOnMethodDeclaration( QualType ArgType; TypeSourceInfo *DI; - if (ArgInfo[i].Type == 0) { + if (!ArgInfo[i].Type) { ArgType = Context.getObjCIdType(); DI = 0; } else { @@ -3001,14 +3191,8 @@ Decl *Sema::ActOnMethodDeclaration( else // Perform the default array/function conversions (C99 6.7.5.3p[7,8]). ArgType = Context.getAdjustedParameterType(ArgType); - if (ArgType->isObjCObjectType()) { - Diag(Param->getLocation(), - diag::err_object_cannot_be_passed_returned_by_value) - << 1 << ArgType; - Param->setInvalidDecl(); - } + Param->setDeclContext(ObjCMethod); - Params.push_back(Param); } @@ -3034,6 +3218,12 @@ Decl *Sema::ActOnMethodDeclaration( if (ObjCInterfaceDecl *IDecl = ImpDecl->getClassInterface()) IMD = IDecl->lookupMethod(ObjCMethod->getSelector(), ObjCMethod->isInstanceMethod()); + if (IMD && IMD->hasAttr<ObjCRequiresSuperAttr>() && + !ObjCMethod->hasAttr<ObjCRequiresSuperAttr>()) { + // merge the attribute into implementation. + ObjCMethod->addAttr( + new (Context) ObjCRequiresSuperAttr(ObjCMethod->getLocation(), Context)); + } if (ObjCMethod->hasAttrs() && containsInvalidMethodImplAttribute(IMD, ObjCMethod->getAttrs())) { SourceLocation MethodLoc = IMD->getLocation(); @@ -3052,6 +3242,8 @@ Decl *Sema::ActOnMethodDeclaration( Diag(ObjCMethod->getLocation(), diag::err_duplicate_method_decl) << ObjCMethod->getDeclName(); Diag(PrevMethod->getLocation(), diag::note_previous_declaration); + ObjCMethod->setInvalidDecl(); + return ObjCMethod; } // If this Objective-C method does not have a related result type, but we @@ -3290,6 +3482,8 @@ void Sema::DiagnoseUseOfUnimplementedSelectors() { ReferencedSelectors[Sels[I].first] = Sels[I].second; } + DiagnoseMismatchedMethodsInGlobalPool(); + // Warning will be issued only when selector table is // generated (which means there is at lease one implementation // in the TU). This is to match gcc's behavior. @@ -3305,3 +3499,43 @@ void Sema::DiagnoseUseOfUnimplementedSelectors() { } return; } + +ObjCIvarDecl * +Sema::GetIvarBackingPropertyAccessor(const ObjCMethodDecl *Method, + const ObjCPropertyDecl *&PDecl) const { + + const ObjCInterfaceDecl *IDecl = Method->getClassInterface(); + if (!IDecl) + return 0; + Method = IDecl->lookupMethod(Method->getSelector(), true); + if (!Method || !Method->isPropertyAccessor()) + return 0; + if ((PDecl = Method->findPropertyDecl())) { + if (!PDecl->getDeclContext()) + return 0; + // Make sure property belongs to accessor's class and not to + // one of its super classes. + if (const ObjCInterfaceDecl *CID = + dyn_cast<ObjCInterfaceDecl>(PDecl->getDeclContext())) + if (CID != IDecl) + return 0; + return PDecl->getPropertyIvarDecl(); + } + return 0; +} + +void Sema::DiagnoseUnusedBackingIvarInAccessor(Scope *S) { + if (S->hasUnrecoverableErrorOccurred() || !S->isInObjcMethodScope()) + return; + + const ObjCMethodDecl *CurMethod = getCurMethodDecl(); + if (!CurMethod) + return; + const ObjCPropertyDecl *PDecl; + const ObjCIvarDecl *IV = GetIvarBackingPropertyAccessor(CurMethod, PDecl); + if (IV && !IV->getBackingIvarReferencedInAccessor()) { + Diag(getCurMethodDecl()->getLocation(), diag::warn_unused_property_backing_ivar) + << IV->getDeclName(); + Diag(PDecl->getLocation(), diag::note_property_declare); + } +} |