forked from OSchip/llvm-project
- Added Sema::AddFactoryMethodToGlobalPool and Sema::AddInstanceMethodToGlobalPool and DenseMaps. This will allow us to efficiently lookup a method from a selector given no type information (for the "id" data type).
- Fixed some funky "} else {" indentation in Sema::ActOnAddMethodsToObjcDecl(). I'd prefer we stay away from this style...it wastes space and isn't any easier to read (from my perspective, at least:-) - Changed Parser::ParseObjCInterfaceDeclList() to only call Action::ActOnAddMethodsToObjcDecl() when it actually has methods to add (since most interface have methods, this is a very minor cleanup). llvm-svn: 42957
This commit is contained in:
parent
a699c4dc65
commit
5811baf1a0
|
@ -266,9 +266,10 @@ void Parser::ParseObjCInterfaceDeclList(DeclTy *interfaceDecl,
|
||||||
ParseDeclarationOrFunctionDefinition();
|
ParseDeclarationOrFunctionDefinition();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// Insert collected methods declarations into the @interface object.
|
if (allMethods.size())
|
||||||
Actions.ActOnAddMethodsToObjcDecl(CurScope, interfaceDecl,
|
/// Insert collected methods declarations into the @interface object.
|
||||||
&allMethods[0], allMethods.size());
|
Actions.ActOnAddMethodsToObjcDecl(CurScope, interfaceDecl,
|
||||||
|
&allMethods[0], allMethods.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse property attribute declarations.
|
/// Parse property attribute declarations.
|
||||||
|
|
|
@ -81,6 +81,7 @@ Decl *ASTStreamer::ReadTopLevelDecl() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ASTStreamer::PrintStats() const {
|
void ASTStreamer::PrintStats() const {
|
||||||
|
P.getActions().PrintStats();
|
||||||
}
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
|
@ -120,6 +120,27 @@ class Sema : public Action {
|
||||||
|
|
||||||
/// ObjcIdTypedef - built-in typedef for "id".
|
/// ObjcIdTypedef - built-in typedef for "id".
|
||||||
TypedefDecl *ObjcIdTypedef;
|
TypedefDecl *ObjcIdTypedef;
|
||||||
|
|
||||||
|
/// ObjCMethodList - a linked list of methods with different signatures.
|
||||||
|
struct ObjcMethodList {
|
||||||
|
ObjcMethodDecl *Method;
|
||||||
|
ObjcMethodList *Next;
|
||||||
|
|
||||||
|
ObjcMethodList() {
|
||||||
|
Method = 0;
|
||||||
|
Next = 0;
|
||||||
|
}
|
||||||
|
ObjcMethodList(ObjcMethodDecl *M, ObjcMethodList *C) {
|
||||||
|
Method = M;
|
||||||
|
Next = C;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
/// Instance/Factory Method Pools - allows efficient lookup when typechecking
|
||||||
|
/// messages to "id". We need to maintain a list, since selectors can have
|
||||||
|
/// differing signatures across classes. In Cocoa, this happens to be
|
||||||
|
/// extremely uncommon (only 1% of selectors are "overloaded").
|
||||||
|
llvm::DenseMap<Selector, ObjcMethodList> InstanceMethodPool;
|
||||||
|
llvm::DenseMap<Selector, ObjcMethodList> FactoryMethodPool;
|
||||||
public:
|
public:
|
||||||
Sema(Preprocessor &pp, ASTContext &ctxt, std::vector<Decl*> &prevInGroup);
|
Sema(Preprocessor &pp, ASTContext &ctxt, std::vector<Decl*> &prevInGroup);
|
||||||
|
|
||||||
|
@ -259,6 +280,14 @@ private:
|
||||||
/// GetObjcIdType - Getter for the build-in "id" type.
|
/// GetObjcIdType - Getter for the build-in "id" type.
|
||||||
QualType GetObjcIdType(SourceLocation Loc = SourceLocation());
|
QualType GetObjcIdType(SourceLocation Loc = SourceLocation());
|
||||||
|
|
||||||
|
/// AddInstanceMethodToGlobalPool - All instance methods in a translation
|
||||||
|
/// unit are added to a global pool. This allows us to efficiently associate
|
||||||
|
/// a selector with a method declaraation for purposes of typechecking
|
||||||
|
/// messages sent to "id" (where the class of the object is unknown).
|
||||||
|
void AddInstanceMethodToGlobalPool(ObjcMethodDecl *Method);
|
||||||
|
|
||||||
|
/// AddFactoryMethodToGlobalPool - Same as above, but for factory methods.
|
||||||
|
void AddFactoryMethodToGlobalPool(ObjcMethodDecl *Method);
|
||||||
//===--------------------------------------------------------------------===//
|
//===--------------------------------------------------------------------===//
|
||||||
// Statement Parsing Callbacks: SemaStmt.cpp.
|
// Statement Parsing Callbacks: SemaStmt.cpp.
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -1754,6 +1754,52 @@ bool Sema:: MatchTwoMethodDeclarations(const ObjcMethodDecl *Method,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Sema::AddInstanceMethodToGlobalPool(ObjcMethodDecl *Method) {
|
||||||
|
ObjcMethodList &FirstMethod = InstanceMethodPool[Method->getSelector()];
|
||||||
|
if (!FirstMethod.Method) {
|
||||||
|
// Haven't seen a method with this selector name yet - add it.
|
||||||
|
FirstMethod.Method = Method;
|
||||||
|
FirstMethod.Next = 0;
|
||||||
|
} else {
|
||||||
|
// We've seen a method with this name, now check the type signature(s).
|
||||||
|
bool match = MatchTwoMethodDeclarations(Method, FirstMethod.Method);
|
||||||
|
|
||||||
|
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.
|
||||||
|
// This is extremely rare. Only 1% of Cocoa selectors are "overloaded".
|
||||||
|
struct ObjcMethodList *OMI = new ObjcMethodList(Method, FirstMethod.Next);
|
||||||
|
FirstMethod.Next = OMI;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Sema::AddFactoryMethodToGlobalPool(ObjcMethodDecl *Method) {
|
||||||
|
ObjcMethodList &FirstMethod = FactoryMethodPool[Method->getSelector()];
|
||||||
|
if (!FirstMethod.Method) {
|
||||||
|
// Haven't seen a method with this selector name yet - add it.
|
||||||
|
FirstMethod.Method = Method;
|
||||||
|
FirstMethod.Next = 0;
|
||||||
|
} else {
|
||||||
|
// We've seen a method with this name, now check the type signature(s).
|
||||||
|
bool match = MatchTwoMethodDeclarations(Method, FirstMethod.Method);
|
||||||
|
|
||||||
|
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.
|
||||||
|
// This is extremely rare. Only 1% of Cocoa selectors are "overloaded".
|
||||||
|
struct ObjcMethodList *OMI = new ObjcMethodList(Method, FirstMethod.Next);
|
||||||
|
FirstMethod.Next = OMI;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Sema::ActOnAddMethodsToObjcDecl(Scope* S, DeclTy *classDecl,
|
void Sema::ActOnAddMethodsToObjcDecl(Scope* S, DeclTy *classDecl,
|
||||||
DeclTy **allMethods, unsigned allNum) {
|
DeclTy **allMethods, unsigned allNum) {
|
||||||
Decl *ClassDecl = static_cast<Decl *>(classDecl);
|
Decl *ClassDecl = static_cast<Decl *>(classDecl);
|
||||||
|
@ -1777,6 +1823,7 @@ void Sema::ActOnAddMethodsToObjcDecl(Scope* S, DeclTy *classDecl,
|
||||||
for (unsigned i = 0; i < allNum; i++ ) {
|
for (unsigned i = 0; i < allNum; i++ ) {
|
||||||
ObjcMethodDecl *Method =
|
ObjcMethodDecl *Method =
|
||||||
cast_or_null<ObjcMethodDecl>(static_cast<Decl*>(allMethods[i]));
|
cast_or_null<ObjcMethodDecl>(static_cast<Decl*>(allMethods[i]));
|
||||||
|
|
||||||
if (!Method) continue; // Already issued a diagnostic.
|
if (!Method) continue; // Already issued a diagnostic.
|
||||||
if (Method->isInstance()) {
|
if (Method->isInstance()) {
|
||||||
if (checkDuplicateMethods) {
|
if (checkDuplicateMethods) {
|
||||||
|
@ -1786,16 +1833,17 @@ void Sema::ActOnAddMethodsToObjcDecl(Scope* S, DeclTy *classDecl,
|
||||||
Diag(Method->getLocation(), diag::error_duplicate_method_decl,
|
Diag(Method->getLocation(), diag::error_duplicate_method_decl,
|
||||||
Method->getSelector().getName());
|
Method->getSelector().getName());
|
||||||
Diag(PrevMethod->getLocation(), diag::err_previous_declaration);
|
Diag(PrevMethod->getLocation(), diag::err_previous_declaration);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
insMethods.push_back(Method);
|
insMethods.push_back(Method);
|
||||||
InsMap[Method->getSelector()] = Method;
|
InsMap[Method->getSelector()] = Method;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
insMethods.push_back(Method);
|
insMethods.push_back(Method);
|
||||||
}
|
|
||||||
else {
|
/// The following allows us to typecheck messages to "id".
|
||||||
|
AddInstanceMethodToGlobalPool(Method);
|
||||||
|
} else {
|
||||||
if (checkDuplicateMethods) {
|
if (checkDuplicateMethods) {
|
||||||
/// Check for class method of the same name with incompatible types
|
/// Check for class method of the same name with incompatible types
|
||||||
const ObjcMethodDecl *&PrevMethod = ClsMap[Method->getSelector()];
|
const ObjcMethodDecl *&PrevMethod = ClsMap[Method->getSelector()];
|
||||||
|
@ -1803,14 +1851,16 @@ void Sema::ActOnAddMethodsToObjcDecl(Scope* S, DeclTy *classDecl,
|
||||||
Diag(Method->getLocation(), diag::error_duplicate_method_decl,
|
Diag(Method->getLocation(), diag::error_duplicate_method_decl,
|
||||||
Method->getSelector().getName());
|
Method->getSelector().getName());
|
||||||
Diag(PrevMethod->getLocation(), diag::err_previous_declaration);
|
Diag(PrevMethod->getLocation(), diag::err_previous_declaration);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
clsMethods.push_back(Method);
|
clsMethods.push_back(Method);
|
||||||
ClsMap[Method->getSelector()] = Method;
|
ClsMap[Method->getSelector()] = Method;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
clsMethods.push_back(Method);
|
clsMethods.push_back(Method);
|
||||||
|
|
||||||
|
/// The following allows us to typecheck messages to "id".
|
||||||
|
AddFactoryMethodToGlobalPool(Method);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -85,6 +85,8 @@ public:
|
||||||
virtual void DeleteExpr(ExprTy *E) {}
|
virtual void DeleteExpr(ExprTy *E) {}
|
||||||
virtual void DeleteStmt(StmtTy *E) {}
|
virtual void DeleteStmt(StmtTy *E) {}
|
||||||
|
|
||||||
|
/// Statistics.
|
||||||
|
virtual void PrintStats() const {}
|
||||||
//===--------------------------------------------------------------------===//
|
//===--------------------------------------------------------------------===//
|
||||||
// Declaration Tracking Callbacks.
|
// Declaration Tracking Callbacks.
|
||||||
//===--------------------------------------------------------------------===//
|
//===--------------------------------------------------------------------===//
|
||||||
|
|
Loading…
Reference in New Issue