[cfe-commits] r56843 - in /cfe/trunk: include/clang/Basic/DiagnosticKinds.def lib/Sema/Sema.h lib/Sema/SemaDeclObjC.cpp lib/Sema/SemaExprObjC.cpp test/SemaObjC/method-lookup-3.m
Steve Naroff
snaroff at apple.com
Tue Sep 30 07:38:43 PDT 2008
Author: snaroff
Date: Tue Sep 30 09:38:43 2008
New Revision: 56843
URL: http://llvm.org/viewvc/llvm-project?rev=56843&view=rev
Log:
Fix <rdar://problem/6191148> [sema] Objective-C method lookup (at global scope) fails to handle overloaded selectors properly.
Long standing bug in Sema::ActOnInstanceMessage(). We now warn when messaging an "id" with multiple method signatures in scope. The diags are a little verbose, however they can be streamlined if necessary.
Added:
cfe/trunk/test/SemaObjC/method-lookup-3.m
Modified:
cfe/trunk/include/clang/Basic/DiagnosticKinds.def
cfe/trunk/lib/Sema/Sema.h
cfe/trunk/lib/Sema/SemaDeclObjC.cpp
cfe/trunk/lib/Sema/SemaExprObjC.cpp
Modified: cfe/trunk/include/clang/Basic/DiagnosticKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticKinds.def?rev=56843&r1=56842&r2=56843&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticKinds.def Tue Sep 30 09:38:43 2008
@@ -467,6 +467,12 @@
"method definition for '%0' not found")
DIAG(warn_incomplete_impl, WARNING,
"incomplete implementation")
+DIAG(warn_multiple_method_decl, WARNING,
+ "multiple methods named '%0' found")
+DIAG(warn_using_decl, WARNING,
+ "using")
+DIAG(warn_also_found_decl, WARNING,
+ "also found")
DIAG(error_duplicate_method_decl, ERROR,
"duplicate declaration of method '%0'")
DIAG(err_previous_declaration, ERROR,
Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=56843&r1=56842&r2=56843&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Tue Sep 30 09:38:43 2008
@@ -379,6 +379,10 @@
/// messages sent to "id" (where the class of the object is unknown).
void AddInstanceMethodToGlobalPool(ObjCMethodDecl *Method);
+ /// LookupInstanceMethodInGlobalPool - Returns the method and warns if
+ /// there are multiple signatures.
+ ObjCMethodDecl *LookupInstanceMethodInGlobalPool(Selector Sel, SourceRange R);
+
/// AddFactoryMethodToGlobalPool - Same as above, but for factory methods.
void AddFactoryMethodToGlobalPool(ObjCMethodDecl *Method);
//===--------------------------------------------------------------------===//
Modified: cfe/trunk/lib/Sema/SemaDeclObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclObjC.cpp?rev=56843&r1=56842&r2=56843&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclObjC.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclObjC.cpp Tue Sep 30 09:38:43 2008
@@ -776,6 +776,21 @@
}
}
+ObjCMethodDecl *Sema::LookupInstanceMethodInGlobalPool(Selector Sel,
+ SourceRange R) {
+ ObjCMethodList &MethList = InstanceMethodPool[Sel];
+
+ if (MethList.Method && MethList.Next) {
+ Diag(R.getBegin(), diag::warn_multiple_method_decl, Sel.getName(), R);
+ Diag(MethList.Method->getLocStart(), diag::warn_using_decl,
+ MethList.Method->getSourceRange());
+ for (ObjCMethodList *Next = MethList.Next; Next; Next = Next->Next)
+ Diag(Next->Method->getLocStart(), diag::warn_also_found_decl,
+ Next->Method->getSourceRange());
+ }
+ return MethList.Method;
+}
+
void Sema::AddFactoryMethodToGlobalPool(ObjCMethodDecl *Method) {
ObjCMethodList &FirstMethod = FactoryMethodPool[Method->getSelector()];
if (!FirstMethod.Method) {
Modified: cfe/trunk/lib/Sema/SemaExprObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprObjC.cpp?rev=56843&r1=56842&r2=56843&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprObjC.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprObjC.cpp Tue Sep 30 09:38:43 2008
@@ -283,7 +283,8 @@
// Handle messages to id.
if (ReceiverCType == Context.getCanonicalType(Context.getObjCIdType()) ||
ReceiverCType->getAsBlockPointerType()) {
- ObjCMethodDecl *Method = InstanceMethodPool[Sel].Method;
+ ObjCMethodDecl *Method = LookupInstanceMethodInGlobalPool(
+ Sel, SourceRange(lbrac,rbrac));
if (!Method)
Method = FactoryMethodPool[Sel].Method;
if (CheckMessageArgumentTypes(ArgExprs, NumArgs, Sel, Method, "-",
@@ -306,7 +307,8 @@
if (!Method)
Method = FactoryMethodPool[Sel].Method;
if (!Method)
- Method = InstanceMethodPool[Sel].Method;
+ Method = LookupInstanceMethodInGlobalPool(
+ Sel, SourceRange(lbrac,rbrac));
if (CheckMessageArgumentTypes(ArgExprs, NumArgs, Sel, Method, "-",
lbrac, rbrac, returnType))
return true;
@@ -335,9 +337,9 @@
// We allow sending a message to a pointer to an interface (an object).
ClassDecl = OCIReceiver->getDecl();
- // FIXME: consider using InstanceMethodPool, since it will be faster
- // than the following method (which can do *many* linear searches). The
- // idea is to add class info to InstanceMethodPool.
+ // FIXME: consider using LookupInstanceMethodInGlobalPool, since it will be
+ // faster than the following method (which can do *many* linear searches).
+ // The idea is to add class info to InstanceMethodPool.
Method = ClassDecl->lookupInstanceMethod(Sel);
if (!Method) {
@@ -369,7 +371,8 @@
// behavior isn't very desirable, however we need it for GCC
// compatibility.
if (!Method)
- Method = InstanceMethodPool[Sel].Method;
+ Method = LookupInstanceMethodInGlobalPool(
+ Sel, SourceRange(lbrac,rbrac));
}
if (CheckMessageArgumentTypes(ArgExprs, NumArgs, Sel, Method, "-",
lbrac, rbrac, returnType))
Added: cfe/trunk/test/SemaObjC/method-lookup-3.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/method-lookup-3.m?rev=56843&view=auto
==============================================================================
--- cfe/trunk/test/SemaObjC/method-lookup-3.m (added)
+++ cfe/trunk/test/SemaObjC/method-lookup-3.m Tue Sep 30 09:38:43 2008
@@ -0,0 +1,52 @@
+// RUN: clang -fsyntax-only -verify %s
+
+typedef struct { int y; } Abstract;
+
+typedef struct { int x; } Alternate;
+
+#define INTERFERE_TYPE Alternate*
+
+ at protocol A
+ at property Abstract *x; // expected-warning{{using}}
+ at end
+
+ at interface B
+ at property Abstract *y; // expected-warning{{using}}
+ at end
+
+ at interface B (Category)
+ at property Abstract *z; // expected-warning{{using}}
+ at end
+
+ at interface InterferencePre
+-(void) x; // expected-warning{{also found}}
+-(void) y; // expected-warning{{also found}}
+-(void) z; // expected-warning{{also found}}
+-(void) setX: (INTERFERE_TYPE) arg; // expected-warning{{also found}}
+-(void) setY: (INTERFERE_TYPE) arg; // expected-warning{{also found}}
+-(void) setZ: (INTERFERE_TYPE) arg; // expected-warning{{also found}}
+ at end
+
+void f0(id a0) {
+ Abstract *l = [a0 x]; // expected-warning {{multiple methods named 'x' found}}
+}
+
+void f1(id a0) {
+ Abstract *l = [a0 y]; // expected-warning {{multiple methods named 'y' found}}
+}
+
+void f2(id a0) {
+ Abstract *l = [a0 z]; // expected-warning {{multiple methods named 'z' found}}
+}
+
+void f3(id a0, Abstract *a1) {
+ [ a0 setX: a1]; // expected-warning {{multiple methods named 'setX:' found}}
+}
+
+void f4(id a0, Abstract *a1) {
+ [ a0 setY: a1]; // expected-warning {{multiple methods named 'setY:' found}}
+}
+
+void f5(id a0, Abstract *a1) {
+ [ a0 setZ: a1]; // expected-warning {{multiple methods named 'setZ:' found}}
+}
More information about the cfe-commits
mailing list