- 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).
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@42957 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/Sema/SemaDecl.cpp b/Sema/SemaDecl.cpp
index 472df15..ef99564 100644
--- a/Sema/SemaDecl.cpp
+++ b/Sema/SemaDecl.cpp
@@ -1754,6 +1754,52 @@
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,
DeclTy **allMethods, unsigned allNum) {
Decl *ClassDecl = static_cast<Decl *>(classDecl);
@@ -1777,6 +1823,7 @@
for (unsigned i = 0; i < allNum; i++ ) {
ObjcMethodDecl *Method =
cast_or_null<ObjcMethodDecl>(static_cast<Decl*>(allMethods[i]));
+
if (!Method) continue; // Already issued a diagnostic.
if (Method->isInstance()) {
if (checkDuplicateMethods) {
@@ -1786,16 +1833,17 @@
Diag(Method->getLocation(), diag::error_duplicate_method_decl,
Method->getSelector().getName());
Diag(PrevMethod->getLocation(), diag::err_previous_declaration);
- }
- else {
+ } else {
insMethods.push_back(Method);
InsMap[Method->getSelector()] = Method;
}
}
else
insMethods.push_back(Method);
- }
- else {
+
+ /// The following allows us to typecheck messages to "id".
+ AddInstanceMethodToGlobalPool(Method);
+ } else {
if (checkDuplicateMethods) {
/// Check for class method of the same name with incompatible types
const ObjcMethodDecl *&PrevMethod = ClsMap[Method->getSelector()];
@@ -1803,14 +1851,16 @@
Diag(Method->getLocation(), diag::error_duplicate_method_decl,
Method->getSelector().getName());
Diag(PrevMethod->getLocation(), diag::err_previous_declaration);
- }
- else {
+ } else {
clsMethods.push_back(Method);
ClsMap[Method->getSelector()] = Method;
}
}
else
clsMethods.push_back(Method);
+
+ /// The following allows us to typecheck messages to "id".
+ AddFactoryMethodToGlobalPool(Method);
}
}