forked from OSchip/llvm-project
atch for implementation of objective-c's -Wselector
warning flag in clang. Little more to do for a PCH issue. Radar 6507158. llvm-svn: 109129
This commit is contained in:
parent
a11b4bfcbe
commit
6e7e8cc19d
|
@ -129,6 +129,9 @@ private:
|
||||||
// Synthesized declaration method for a property setter/getter
|
// Synthesized declaration method for a property setter/getter
|
||||||
bool IsSynthesized : 1;
|
bool IsSynthesized : 1;
|
||||||
|
|
||||||
|
// Method has a definition.
|
||||||
|
bool IsDefined : 1;
|
||||||
|
|
||||||
// NOTE: VC++ treats enums as signed, avoid using ImplementationControl enum
|
// NOTE: VC++ treats enums as signed, avoid using ImplementationControl enum
|
||||||
/// @required/@optional
|
/// @required/@optional
|
||||||
unsigned DeclImplementation : 2;
|
unsigned DeclImplementation : 2;
|
||||||
|
@ -171,12 +174,14 @@ private:
|
||||||
bool isInstance = true,
|
bool isInstance = true,
|
||||||
bool isVariadic = false,
|
bool isVariadic = false,
|
||||||
bool isSynthesized = false,
|
bool isSynthesized = false,
|
||||||
|
bool isDefined = false,
|
||||||
ImplementationControl impControl = None,
|
ImplementationControl impControl = None,
|
||||||
unsigned numSelectorArgs = 0)
|
unsigned numSelectorArgs = 0)
|
||||||
: NamedDecl(ObjCMethod, contextDecl, beginLoc, SelInfo),
|
: NamedDecl(ObjCMethod, contextDecl, beginLoc, SelInfo),
|
||||||
DeclContext(ObjCMethod),
|
DeclContext(ObjCMethod),
|
||||||
IsInstance(isInstance), IsVariadic(isVariadic),
|
IsInstance(isInstance), IsVariadic(isVariadic),
|
||||||
IsSynthesized(isSynthesized),
|
IsSynthesized(isSynthesized),
|
||||||
|
IsDefined(isDefined),
|
||||||
DeclImplementation(impControl), objcDeclQualifier(OBJC_TQ_None),
|
DeclImplementation(impControl), objcDeclQualifier(OBJC_TQ_None),
|
||||||
NumSelectorArgs(numSelectorArgs), MethodDeclType(T),
|
NumSelectorArgs(numSelectorArgs), MethodDeclType(T),
|
||||||
ResultTInfo(ResultTInfo),
|
ResultTInfo(ResultTInfo),
|
||||||
|
@ -203,6 +208,7 @@ public:
|
||||||
bool isInstance = true,
|
bool isInstance = true,
|
||||||
bool isVariadic = false,
|
bool isVariadic = false,
|
||||||
bool isSynthesized = false,
|
bool isSynthesized = false,
|
||||||
|
bool isDefined = false,
|
||||||
ImplementationControl impControl = None,
|
ImplementationControl impControl = None,
|
||||||
unsigned numSelectorArgs = 0);
|
unsigned numSelectorArgs = 0);
|
||||||
|
|
||||||
|
@ -297,6 +303,9 @@ public:
|
||||||
bool isSynthesized() const { return IsSynthesized; }
|
bool isSynthesized() const { return IsSynthesized; }
|
||||||
void setSynthesized(bool isSynth) { IsSynthesized = isSynth; }
|
void setSynthesized(bool isSynth) { IsSynthesized = isSynth; }
|
||||||
|
|
||||||
|
bool isDefined() const { return IsDefined; }
|
||||||
|
void setDefined(bool isDefined) { IsDefined = isDefined; }
|
||||||
|
|
||||||
// Related to protocols declared in @protocol
|
// Related to protocols declared in @protocol
|
||||||
void setDeclImplementation(ImplementationControl ic) {
|
void setDeclImplementation(ImplementationControl ic) {
|
||||||
DeclImplementation = ic;
|
DeclImplementation = ic;
|
||||||
|
|
|
@ -134,6 +134,7 @@ def UnusedVariable : DiagGroup<"unused-variable">;
|
||||||
def ReadOnlySetterAttrs : DiagGroup<"readonly-setter-attrs">;
|
def ReadOnlySetterAttrs : DiagGroup<"readonly-setter-attrs">;
|
||||||
def Reorder : DiagGroup<"reorder">;
|
def Reorder : DiagGroup<"reorder">;
|
||||||
def UndeclaredSelector : DiagGroup<"undeclared-selector">;
|
def UndeclaredSelector : DiagGroup<"undeclared-selector">;
|
||||||
|
def Selector : DiagGroup<"selector">;
|
||||||
def Protocol : DiagGroup<"protocol">;
|
def Protocol : DiagGroup<"protocol">;
|
||||||
def SuperSubClassMismatch : DiagGroup<"super-class-method-mismatch">;
|
def SuperSubClassMismatch : DiagGroup<"super-class-method-mismatch">;
|
||||||
def : DiagGroup<"variadic-macros">;
|
def : DiagGroup<"variadic-macros">;
|
||||||
|
|
|
@ -400,6 +400,8 @@ def warn_objc_property_attr_mutually_exclusive : Warning<
|
||||||
InGroup<ReadOnlySetterAttrs>, DefaultIgnore;
|
InGroup<ReadOnlySetterAttrs>, DefaultIgnore;
|
||||||
def warn_undeclared_selector : Warning<
|
def warn_undeclared_selector : Warning<
|
||||||
"undeclared selector %0">, InGroup<UndeclaredSelector>, DefaultIgnore;
|
"undeclared selector %0">, InGroup<UndeclaredSelector>, DefaultIgnore;
|
||||||
|
def warn_unimplemented_selector: Warning<
|
||||||
|
"unimplemented selector %0">, InGroup<Selector>, DefaultIgnore;
|
||||||
def warn_unimplemented_protocol_method : Warning<
|
def warn_unimplemented_protocol_method : Warning<
|
||||||
"method in protocol not implemented">, InGroup<Protocol>;
|
"method in protocol not implemented">, InGroup<Protocol>;
|
||||||
|
|
||||||
|
|
|
@ -202,6 +202,8 @@ public:
|
||||||
return DeclGroupPtrTy();
|
return DeclGroupPtrTy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void DiagnoseUseOfUnimplementedSelectors() {}
|
||||||
|
|
||||||
/// getTypeName - Return non-null if the specified identifier is a type name
|
/// getTypeName - Return non-null if the specified identifier is a type name
|
||||||
/// in the current scope.
|
/// in the current scope.
|
||||||
///
|
///
|
||||||
|
|
|
@ -201,7 +201,7 @@ public:
|
||||||
/// the EOF was encountered.
|
/// the EOF was encountered.
|
||||||
bool ParseTopLevelDecl(DeclGroupPtrTy &Result);
|
bool ParseTopLevelDecl(DeclGroupPtrTy &Result);
|
||||||
|
|
||||||
DeclGroupPtrTy RetrievePendingObjCImpDecl();
|
DeclGroupPtrTy FinishPendingObjCActions();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
//===--------------------------------------------------------------------===//
|
//===--------------------------------------------------------------------===//
|
||||||
|
|
|
@ -2299,6 +2299,7 @@ Decl *ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) {
|
||||||
D->isInstanceMethod(),
|
D->isInstanceMethod(),
|
||||||
D->isVariadic(),
|
D->isVariadic(),
|
||||||
D->isSynthesized(),
|
D->isSynthesized(),
|
||||||
|
D->isDefined(),
|
||||||
D->getImplementationControl());
|
D->getImplementationControl());
|
||||||
|
|
||||||
// FIXME: When we decide to merge method definitions, we'll need to
|
// FIXME: When we decide to merge method definitions, we'll need to
|
||||||
|
|
|
@ -339,12 +339,14 @@ ObjCMethodDecl *ObjCMethodDecl::Create(ASTContext &C,
|
||||||
bool isInstance,
|
bool isInstance,
|
||||||
bool isVariadic,
|
bool isVariadic,
|
||||||
bool isSynthesized,
|
bool isSynthesized,
|
||||||
|
bool isDefined,
|
||||||
ImplementationControl impControl,
|
ImplementationControl impControl,
|
||||||
unsigned numSelectorArgs) {
|
unsigned numSelectorArgs) {
|
||||||
return new (C) ObjCMethodDecl(beginLoc, endLoc,
|
return new (C) ObjCMethodDecl(beginLoc, endLoc,
|
||||||
SelInfo, T, ResultTInfo, contextDecl,
|
SelInfo, T, ResultTInfo, contextDecl,
|
||||||
isInstance,
|
isInstance,
|
||||||
isVariadic, isSynthesized, impControl,
|
isVariadic, isSynthesized, isDefined,
|
||||||
|
impControl,
|
||||||
numSelectorArgs);
|
numSelectorArgs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1930,7 +1930,7 @@ void CodeGenModule::EmitObjCIvarInitializations(ObjCImplementationDecl *D) {
|
||||||
D->getLocation(),
|
D->getLocation(),
|
||||||
D->getLocation(), cxxSelector,
|
D->getLocation(), cxxSelector,
|
||||||
getContext().VoidTy, 0,
|
getContext().VoidTy, 0,
|
||||||
DC, true, false, true,
|
DC, true, false, true, false,
|
||||||
ObjCMethodDecl::Required);
|
ObjCMethodDecl::Required);
|
||||||
D->addInstanceMethod(DTORMethod);
|
D->addInstanceMethod(DTORMethod);
|
||||||
CodeGenFunction(*this).GenerateObjCCtorDtorMethod(D, DTORMethod, false);
|
CodeGenFunction(*this).GenerateObjCCtorDtorMethod(D, DTORMethod, false);
|
||||||
|
@ -1942,7 +1942,7 @@ void CodeGenModule::EmitObjCIvarInitializations(ObjCImplementationDecl *D) {
|
||||||
D->getLocation(),
|
D->getLocation(),
|
||||||
D->getLocation(), cxxSelector,
|
D->getLocation(), cxxSelector,
|
||||||
getContext().getObjCIdType(), 0,
|
getContext().getObjCIdType(), 0,
|
||||||
DC, true, false, true,
|
DC, true, false, true, false,
|
||||||
ObjCMethodDecl::Required);
|
ObjCMethodDecl::Required);
|
||||||
D->addInstanceMethod(CTORMethod);
|
D->addInstanceMethod(CTORMethod);
|
||||||
CodeGenFunction(*this).GenerateObjCCtorDtorMethod(D, CTORMethod, true);
|
CodeGenFunction(*this).GenerateObjCCtorDtorMethod(D, CTORMethod, true);
|
||||||
|
|
|
@ -324,6 +324,7 @@ void PCHDeclReader::VisitObjCMethodDecl(ObjCMethodDecl *MD) {
|
||||||
MD->setInstanceMethod(Record[Idx++]);
|
MD->setInstanceMethod(Record[Idx++]);
|
||||||
MD->setVariadic(Record[Idx++]);
|
MD->setVariadic(Record[Idx++]);
|
||||||
MD->setSynthesized(Record[Idx++]);
|
MD->setSynthesized(Record[Idx++]);
|
||||||
|
MD->setDefined(Record[Idx++]);
|
||||||
MD->setDeclImplementation((ObjCMethodDecl::ImplementationControl)Record[Idx++]);
|
MD->setDeclImplementation((ObjCMethodDecl::ImplementationControl)Record[Idx++]);
|
||||||
MD->setObjCDeclQualifier((Decl::ObjCDeclQualifier)Record[Idx++]);
|
MD->setObjCDeclQualifier((Decl::ObjCDeclQualifier)Record[Idx++]);
|
||||||
MD->setNumSelectorArgs(unsigned(Record[Idx++]));
|
MD->setNumSelectorArgs(unsigned(Record[Idx++]));
|
||||||
|
|
|
@ -312,6 +312,7 @@ void PCHDeclWriter::VisitObjCMethodDecl(ObjCMethodDecl *D) {
|
||||||
Record.push_back(D->isInstanceMethod());
|
Record.push_back(D->isInstanceMethod());
|
||||||
Record.push_back(D->isVariadic());
|
Record.push_back(D->isVariadic());
|
||||||
Record.push_back(D->isSynthesized());
|
Record.push_back(D->isSynthesized());
|
||||||
|
Record.push_back(D->isDefined());
|
||||||
// FIXME: stable encoding for @required/@optional
|
// FIXME: stable encoding for @required/@optional
|
||||||
Record.push_back(D->getImplementationControl());
|
Record.push_back(D->getImplementationControl());
|
||||||
// FIXME: stable encoding for in/out/inout/bycopy/byref/oneway
|
// FIXME: stable encoding for in/out/inout/bycopy/byref/oneway
|
||||||
|
|
|
@ -1314,7 +1314,8 @@ Parser::DeclPtrTy Parser::ParseObjCAtEndDeclaration(SourceRange atEnd) {
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Parser::DeclGroupPtrTy Parser::RetrievePendingObjCImpDecl() {
|
Parser::DeclGroupPtrTy Parser::FinishPendingObjCActions() {
|
||||||
|
Actions.DiagnoseUseOfUnimplementedSelectors();
|
||||||
if (PendingObjCImpDecl.empty())
|
if (PendingObjCImpDecl.empty())
|
||||||
return Actions.ConvertDeclToDeclGroup(DeclPtrTy());
|
return Actions.ConvertDeclToDeclGroup(DeclPtrTy());
|
||||||
DeclPtrTy ImpDecl = PendingObjCImpDecl.pop_back_val();
|
DeclPtrTy ImpDecl = PendingObjCImpDecl.pop_back_val();
|
||||||
|
|
|
@ -92,7 +92,7 @@ void clang::ParseAST(Preprocessor &PP, ASTConsumer *Consumer,
|
||||||
Consumer->HandleTopLevelDecl(ADecl.getAsVal<DeclGroupRef>());
|
Consumer->HandleTopLevelDecl(ADecl.getAsVal<DeclGroupRef>());
|
||||||
};
|
};
|
||||||
// Check for any pending objective-c implementation decl.
|
// Check for any pending objective-c implementation decl.
|
||||||
while ((ADecl = P.RetrievePendingObjCImpDecl()))
|
while ((ADecl = P.FinishPendingObjCActions()))
|
||||||
Consumer->HandleTopLevelDecl(ADecl.getAsVal<DeclGroupRef>());
|
Consumer->HandleTopLevelDecl(ADecl.getAsVal<DeclGroupRef>());
|
||||||
|
|
||||||
// Process any TopLevelDecls generated by #pragma weak.
|
// Process any TopLevelDecls generated by #pragma weak.
|
||||||
|
|
|
@ -606,6 +606,11 @@ public:
|
||||||
MethodPool InstanceMethodPool;
|
MethodPool InstanceMethodPool;
|
||||||
MethodPool FactoryMethodPool;
|
MethodPool FactoryMethodPool;
|
||||||
|
|
||||||
|
/// Method selectors used in a @selector expression. Used for implementation
|
||||||
|
/// of -Wselector.
|
||||||
|
llvm::DenseMap<Selector, SourceLocation> ReferencedSelectors;
|
||||||
|
|
||||||
|
|
||||||
MethodPool::iterator ReadMethodPool(Selector Sel, bool isInstance);
|
MethodPool::iterator ReadMethodPool(Selector Sel, bool isInstance);
|
||||||
|
|
||||||
/// Private Helper predicate to check for 'self'.
|
/// Private Helper predicate to check for 'self'.
|
||||||
|
@ -798,6 +803,8 @@ public:
|
||||||
|
|
||||||
DeclGroupPtrTy ConvertDeclToDeclGroup(DeclPtrTy Ptr);
|
DeclGroupPtrTy ConvertDeclToDeclGroup(DeclPtrTy Ptr);
|
||||||
|
|
||||||
|
void DiagnoseUseOfUnimplementedSelectors();
|
||||||
|
|
||||||
virtual TypeTy *getTypeName(IdentifierInfo &II, SourceLocation NameLoc,
|
virtual TypeTy *getTypeName(IdentifierInfo &II, SourceLocation NameLoc,
|
||||||
Scope *S, CXXScopeSpec *SS,
|
Scope *S, CXXScopeSpec *SS,
|
||||||
bool isClassName = false,
|
bool isClassName = false,
|
||||||
|
@ -1656,7 +1663,7 @@ public:
|
||||||
/// unit are added to a global pool. This allows us to efficiently associate
|
/// unit are added to a global pool. This allows us to efficiently associate
|
||||||
/// a selector with a method declaraation for purposes of typechecking
|
/// a selector with a method declaraation for purposes of typechecking
|
||||||
/// messages sent to "id" (where the class of the object is unknown).
|
/// messages sent to "id" (where the class of the object is unknown).
|
||||||
void AddInstanceMethodToGlobalPool(ObjCMethodDecl *Method);
|
void AddInstanceMethodToGlobalPool(ObjCMethodDecl *Method, bool impl=false);
|
||||||
|
|
||||||
/// LookupInstanceMethodInGlobalPool - Returns the method and warns if
|
/// LookupInstanceMethodInGlobalPool - Returns the method and warns if
|
||||||
/// there are multiple signatures.
|
/// there are multiple signatures.
|
||||||
|
@ -1665,10 +1672,15 @@ public:
|
||||||
|
|
||||||
/// LookupFactoryMethodInGlobalPool - Returns the method and warns if
|
/// LookupFactoryMethodInGlobalPool - Returns the method and warns if
|
||||||
/// there are multiple signatures.
|
/// there are multiple signatures.
|
||||||
ObjCMethodDecl *LookupFactoryMethodInGlobalPool(Selector Sel, SourceRange R);
|
ObjCMethodDecl *LookupFactoryMethodInGlobalPool(Selector Sel, SourceRange R,
|
||||||
|
bool warn=true);
|
||||||
|
|
||||||
|
/// LookupImplementedMethodInGlobalPool - Returns the method which has an
|
||||||
|
/// implementation.
|
||||||
|
ObjCMethodDecl *LookupImplementedMethodInGlobalPool(Selector Sel);
|
||||||
|
|
||||||
/// AddFactoryMethodToGlobalPool - Same as above, but for factory methods.
|
/// AddFactoryMethodToGlobalPool - Same as above, but for factory methods.
|
||||||
void AddFactoryMethodToGlobalPool(ObjCMethodDecl *Method);
|
void AddFactoryMethodToGlobalPool(ObjCMethodDecl *Method, bool impl=false);
|
||||||
|
|
||||||
/// CollectIvarsToConstructOrDestruct - Collect those ivars which require
|
/// CollectIvarsToConstructOrDestruct - Collect those ivars which require
|
||||||
/// initialization.
|
/// initialization.
|
||||||
|
|
|
@ -32,9 +32,9 @@ void Sema::ActOnStartOfObjCMethodDef(Scope *FnBodyScope, DeclPtrTy D) {
|
||||||
|
|
||||||
// Allow the rest of sema to find private method decl implementations.
|
// Allow the rest of sema to find private method decl implementations.
|
||||||
if (MDecl->isInstanceMethod())
|
if (MDecl->isInstanceMethod())
|
||||||
AddInstanceMethodToGlobalPool(MDecl);
|
AddInstanceMethodToGlobalPool(MDecl, true);
|
||||||
else
|
else
|
||||||
AddFactoryMethodToGlobalPool(MDecl);
|
AddFactoryMethodToGlobalPool(MDecl, true);
|
||||||
|
|
||||||
// Allow all of Sema to see that we are entering a method definition.
|
// Allow all of Sema to see that we are entering a method definition.
|
||||||
PushDeclContext(FnBodyScope, MDecl);
|
PushDeclContext(FnBodyScope, MDecl);
|
||||||
|
@ -1130,7 +1130,7 @@ Sema::MethodPool::iterator Sema::ReadMethodPool(Selector Sel,
|
||||||
return FactoryMethodPool.insert(std::make_pair(Sel, Methods.second)).first;
|
return FactoryMethodPool.insert(std::make_pair(Sel, Methods.second)).first;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sema::AddInstanceMethodToGlobalPool(ObjCMethodDecl *Method) {
|
void Sema::AddInstanceMethodToGlobalPool(ObjCMethodDecl *Method, bool impl) {
|
||||||
llvm::DenseMap<Selector, ObjCMethodList>::iterator Pos
|
llvm::DenseMap<Selector, ObjCMethodList>::iterator Pos
|
||||||
= InstanceMethodPool.find(Method->getSelector());
|
= InstanceMethodPool.find(Method->getSelector());
|
||||||
if (Pos == InstanceMethodPool.end()) {
|
if (Pos == InstanceMethodPool.end()) {
|
||||||
|
@ -1140,7 +1140,7 @@ void Sema::AddInstanceMethodToGlobalPool(ObjCMethodDecl *Method) {
|
||||||
Pos = InstanceMethodPool.insert(std::make_pair(Method->getSelector(),
|
Pos = InstanceMethodPool.insert(std::make_pair(Method->getSelector(),
|
||||||
ObjCMethodList())).first;
|
ObjCMethodList())).first;
|
||||||
}
|
}
|
||||||
|
Method->setDefined(impl);
|
||||||
ObjCMethodList &Entry = Pos->second;
|
ObjCMethodList &Entry = Pos->second;
|
||||||
if (Entry.Method == 0) {
|
if (Entry.Method == 0) {
|
||||||
// Haven't seen a method with this selector name yet - add it.
|
// Haven't seen a method with this selector name yet - add it.
|
||||||
|
@ -1152,8 +1152,10 @@ void Sema::AddInstanceMethodToGlobalPool(ObjCMethodDecl *Method) {
|
||||||
// We've seen a method with this name, see if we have already seen this type
|
// We've seen a method with this name, see if we have already seen this type
|
||||||
// signature.
|
// signature.
|
||||||
for (ObjCMethodList *List = &Entry; List; List = List->Next)
|
for (ObjCMethodList *List = &Entry; List; List = List->Next)
|
||||||
if (MatchTwoMethodDeclarations(Method, List->Method))
|
if (MatchTwoMethodDeclarations(Method, List->Method)) {
|
||||||
|
List->Method->setDefined(impl);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// We have a new signature for an existing method - add it.
|
// We have a new signature for an existing method - add it.
|
||||||
// This is extremely rare. Only 1% of Cocoa selectors are "overloaded".
|
// This is extremely rare. Only 1% of Cocoa selectors are "overloaded".
|
||||||
|
@ -1194,7 +1196,7 @@ ObjCMethodDecl *Sema::LookupInstanceMethodInGlobalPool(Selector Sel,
|
||||||
return MethList.Method;
|
return MethList.Method;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sema::AddFactoryMethodToGlobalPool(ObjCMethodDecl *Method) {
|
void Sema::AddFactoryMethodToGlobalPool(ObjCMethodDecl *Method, bool impl) {
|
||||||
llvm::DenseMap<Selector, ObjCMethodList>::iterator Pos
|
llvm::DenseMap<Selector, ObjCMethodList>::iterator Pos
|
||||||
= FactoryMethodPool.find(Method->getSelector());
|
= FactoryMethodPool.find(Method->getSelector());
|
||||||
if (Pos == FactoryMethodPool.end()) {
|
if (Pos == FactoryMethodPool.end()) {
|
||||||
|
@ -1204,32 +1206,31 @@ void Sema::AddFactoryMethodToGlobalPool(ObjCMethodDecl *Method) {
|
||||||
Pos = FactoryMethodPool.insert(std::make_pair(Method->getSelector(),
|
Pos = FactoryMethodPool.insert(std::make_pair(Method->getSelector(),
|
||||||
ObjCMethodList())).first;
|
ObjCMethodList())).first;
|
||||||
}
|
}
|
||||||
|
Method->setDefined(impl);
|
||||||
ObjCMethodList &FirstMethod = Pos->second;
|
ObjCMethodList &Entry = Pos->second;
|
||||||
if (!FirstMethod.Method) {
|
if (!Entry.Method) {
|
||||||
// Haven't seen a method with this selector name yet - add it.
|
// Haven't seen a method with this selector name yet - add it.
|
||||||
FirstMethod.Method = Method;
|
Entry.Method = Method;
|
||||||
FirstMethod.Next = 0;
|
Entry.Next = 0;
|
||||||
} else {
|
return;
|
||||||
// We've seen a method with this name, now check the type signature(s).
|
}
|
||||||
bool match = MatchTwoMethodDeclarations(Method, FirstMethod.Method);
|
// We've seen a method with this name, see if we have already seen this type
|
||||||
|
// signature.
|
||||||
|
for (ObjCMethodList *List = &Entry; List; List = List->Next)
|
||||||
|
if (MatchTwoMethodDeclarations(Method, List->Method)) {
|
||||||
|
List->Method->setDefined(impl);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
for (ObjCMethodList *Next = FirstMethod.Next; !match && Next;
|
|
||||||
Next = Next->Next)
|
|
||||||
match = MatchTwoMethodDeclarations(Method, Next->Method);
|
|
||||||
|
|
||||||
if (!match) {
|
|
||||||
// We have a new signature for an existing method - add it.
|
// We have a new signature for an existing method - add it.
|
||||||
// This is extremely rare. Only 1% of Cocoa selectors are "overloaded".
|
// This is extremely rare. Only 1% of Cocoa selectors are "overloaded".
|
||||||
ObjCMethodList *Mem = BumpAlloc.Allocate<ObjCMethodList>();
|
ObjCMethodList *Mem = BumpAlloc.Allocate<ObjCMethodList>();
|
||||||
ObjCMethodList *OMI = new (Mem) ObjCMethodList(Method, FirstMethod.Next);
|
Entry.Next = new (Mem) ObjCMethodList(Method, Entry.Next);
|
||||||
FirstMethod.Next = OMI;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ObjCMethodDecl *Sema::LookupFactoryMethodInGlobalPool(Selector Sel,
|
ObjCMethodDecl *Sema::LookupFactoryMethodInGlobalPool(Selector Sel,
|
||||||
SourceRange R) {
|
SourceRange R,
|
||||||
|
bool warn) {
|
||||||
llvm::DenseMap<Selector, ObjCMethodList>::iterator Pos
|
llvm::DenseMap<Selector, ObjCMethodList>::iterator Pos
|
||||||
= FactoryMethodPool.find(Sel);
|
= FactoryMethodPool.find(Sel);
|
||||||
if (Pos == FactoryMethodPool.end()) {
|
if (Pos == FactoryMethodPool.end()) {
|
||||||
|
@ -1246,7 +1247,7 @@ ObjCMethodDecl *Sema::LookupFactoryMethodInGlobalPool(Selector Sel,
|
||||||
for (ObjCMethodList *Next = MethList.Next; Next; Next = Next->Next)
|
for (ObjCMethodList *Next = MethList.Next; Next; Next = Next->Next)
|
||||||
// This checks if the methods differ by size & alignment.
|
// This checks if the methods differ by size & alignment.
|
||||||
if (!MatchTwoMethodDeclarations(MethList.Method, Next->Method, true))
|
if (!MatchTwoMethodDeclarations(MethList.Method, Next->Method, true))
|
||||||
issueWarning = true;
|
issueWarning = warn;
|
||||||
}
|
}
|
||||||
if (issueWarning && (MethList.Method && MethList.Next)) {
|
if (issueWarning && (MethList.Method && MethList.Next)) {
|
||||||
Diag(R.getBegin(), diag::warn_multiple_method_decl) << Sel << R;
|
Diag(R.getBegin(), diag::warn_multiple_method_decl) << Sel << R;
|
||||||
|
@ -1259,6 +1260,18 @@ ObjCMethodDecl *Sema::LookupFactoryMethodInGlobalPool(Selector Sel,
|
||||||
return MethList.Method;
|
return MethList.Method;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ObjCMethodDecl *Sema::LookupImplementedMethodInGlobalPool(Selector Sel) {
|
||||||
|
SourceRange SR;
|
||||||
|
ObjCMethodDecl *Method = LookupInstanceMethodInGlobalPool(Sel,
|
||||||
|
SR, false);
|
||||||
|
if (Method && Method->isDefined())
|
||||||
|
return Method;
|
||||||
|
Method = LookupFactoryMethodInGlobalPool(Sel, SR, false);
|
||||||
|
if (Method && Method->isDefined())
|
||||||
|
return Method;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/// CompareMethodParamsInBaseAndSuper - This routine compares methods with
|
/// CompareMethodParamsInBaseAndSuper - This routine compares methods with
|
||||||
/// identical selector names in current and its super classes and issues
|
/// identical selector names in current and its super classes and issues
|
||||||
/// a warning if any of their argument types are incompatible.
|
/// a warning if any of their argument types are incompatible.
|
||||||
|
@ -1540,7 +1553,7 @@ Sema::DeclPtrTy Sema::ActOnMethodDeclaration(
|
||||||
ResultTInfo,
|
ResultTInfo,
|
||||||
cast<DeclContext>(ClassDecl),
|
cast<DeclContext>(ClassDecl),
|
||||||
MethodType == tok::minus, isVariadic,
|
MethodType == tok::minus, isVariadic,
|
||||||
false,
|
false, false,
|
||||||
MethodDeclKind == tok::objc_optional ?
|
MethodDeclKind == tok::objc_optional ?
|
||||||
ObjCMethodDecl::Optional :
|
ObjCMethodDecl::Optional :
|
||||||
ObjCMethodDecl::Required);
|
ObjCMethodDecl::Required);
|
||||||
|
@ -1849,3 +1862,15 @@ void ObjCImplementationDecl::setIvarInitializers(ASTContext &C,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Sema::DiagnoseUseOfUnimplementedSelectors() {
|
||||||
|
if (ReferencedSelectors.empty())
|
||||||
|
return;
|
||||||
|
for (llvm::DenseMap<Selector, SourceLocation>::iterator S =
|
||||||
|
ReferencedSelectors.begin(),
|
||||||
|
E = ReferencedSelectors.end(); S != E; ++S) {
|
||||||
|
Selector Sel = (*S).first;
|
||||||
|
if (!LookupImplementedMethodInGlobalPool(Sel))
|
||||||
|
Diag((*S).second, diag::warn_unimplemented_selector) << Sel;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
|
@ -163,6 +163,11 @@ Sema::ExprResult Sema::ParseObjCSelectorExpression(Selector Sel,
|
||||||
if (!Method)
|
if (!Method)
|
||||||
Diag(SelLoc, diag::warn_undeclared_selector) << Sel;
|
Diag(SelLoc, diag::warn_undeclared_selector) << Sel;
|
||||||
|
|
||||||
|
llvm::DenseMap<Selector, SourceLocation>::iterator Pos
|
||||||
|
= ReferencedSelectors.find(Sel);
|
||||||
|
if (Pos == ReferencedSelectors.end())
|
||||||
|
ReferencedSelectors.insert(std::make_pair(Sel, SelLoc));
|
||||||
|
|
||||||
QualType Ty = Context.getObjCSelType();
|
QualType Ty = Context.getObjCSelType();
|
||||||
return new (Context) ObjCSelectorExpr(Ty, Sel, AtLoc, RParenLoc);
|
return new (Context) ObjCSelectorExpr(Ty, Sel, AtLoc, RParenLoc);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1085,6 +1085,7 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property,
|
||||||
GetterMethod = ObjCMethodDecl::Create(Context, property->getLocation(),
|
GetterMethod = ObjCMethodDecl::Create(Context, property->getLocation(),
|
||||||
property->getLocation(), property->getGetterName(),
|
property->getLocation(), property->getGetterName(),
|
||||||
property->getType(), 0, CD, true, false, true,
|
property->getType(), 0, CD, true, false, true,
|
||||||
|
false,
|
||||||
(property->getPropertyImplementation() ==
|
(property->getPropertyImplementation() ==
|
||||||
ObjCPropertyDecl::Optional) ?
|
ObjCPropertyDecl::Optional) ?
|
||||||
ObjCMethodDecl::Optional :
|
ObjCMethodDecl::Optional :
|
||||||
|
@ -1112,6 +1113,7 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property,
|
||||||
property->getLocation(),
|
property->getLocation(),
|
||||||
property->getSetterName(),
|
property->getSetterName(),
|
||||||
Context.VoidTy, 0, CD, true, false, true,
|
Context.VoidTy, 0, CD, true, false, true,
|
||||||
|
false,
|
||||||
(property->getPropertyImplementation() ==
|
(property->getPropertyImplementation() ==
|
||||||
ObjCPropertyDecl::Optional) ?
|
ObjCPropertyDecl::Optional) ?
|
||||||
ObjCMethodDecl::Optional :
|
ObjCMethodDecl::Optional :
|
||||||
|
|
Loading…
Reference in New Issue