summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp')
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp408
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);
+ }
+}
OpenPOWER on IntegriCloud