[cfe-commits] r129016 - in /cfe/trunk: include/clang/AST/Type.h include/clang/Basic/DiagnosticSemaKinds.td lib/AST/Type.cpp lib/Sema/SemaExprObjC.cpp test/SemaObjC/class-message-protocol-lookup.m
Fariborz Jahanian
fjahanian at apple.com
Wed Apr 6 11:40:08 PDT 2011
Author: fjahanian
Date: Wed Apr 6 13:40:08 2011
New Revision: 129016
URL: http://llvm.org/viewvc/llvm-project?rev=129016&view=rev
Log:
Fix lookup for class messages sent to qualified-class
types such that protocols are seached first. Fixes
// rdar://9224670
Added:
cfe/trunk/test/SemaObjC/class-message-protocol-lookup.m
Modified:
cfe/trunk/include/clang/AST/Type.h
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/lib/AST/Type.cpp
cfe/trunk/lib/Sema/SemaExprObjC.cpp
Modified: cfe/trunk/include/clang/AST/Type.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=129016&r1=129015&r2=129016&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Type.h (original)
+++ cfe/trunk/include/clang/AST/Type.h Wed Apr 6 13:40:08 2011
@@ -1327,6 +1327,7 @@
// for object declared using an interface.
const ObjCObjectPointerType *getAsObjCInterfacePointerType() const;
const ObjCObjectPointerType *getAsObjCQualifiedIdType() const;
+ const ObjCObjectPointerType *getAsObjCQualifiedClassType() const;
const ObjCObjectType *getAsObjCQualifiedInterfaceType() const;
const CXXRecordDecl *getCXXRecordDeclForPointerType() const;
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=129016&r1=129015&r2=129016&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Wed Apr 6 13:40:08 2011
@@ -2724,6 +2724,8 @@
"instance method %0 is being used on 'Class' which is not in the root class">;
def warn_class_method_not_found : Warning<
"class method %objcclass0 not found (return type defaults to 'id')">;
+def warn_instance_method_on_class_found : Warning<
+ "instance method %0 found instead of class method %1">;
def warn_inst_method_not_found : Warning<
"instance method %objcinstance0 not found (return type defaults to 'id')">;
def error_no_super_class_message : Error<
Modified: cfe/trunk/lib/AST/Type.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Type.cpp?rev=129016&r1=129015&r2=129016&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Type.cpp (original)
+++ cfe/trunk/lib/AST/Type.cpp Wed Apr 6 13:40:08 2011
@@ -408,6 +408,16 @@
return 0;
}
+const ObjCObjectPointerType *Type::getAsObjCQualifiedClassType() const {
+ // There is no sugar for ObjCQualifiedClassType's, just return the canonical
+ // type pointer if it is the right class.
+ if (const ObjCObjectPointerType *OPT = getAs<ObjCObjectPointerType>()) {
+ if (OPT->isObjCQualifiedClassType())
+ return OPT;
+ }
+ return 0;
+}
+
const ObjCObjectPointerType *Type::getAsObjCInterfacePointerType() const {
if (const ObjCObjectPointerType *OPT = getAs<ObjCObjectPointerType>()) {
if (OPT->getInterfaceType())
Modified: cfe/trunk/lib/Sema/SemaExprObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprObjC.cpp?rev=129016&r1=129015&r2=129016&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprObjC.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprObjC.cpp Wed Apr 6 13:40:08 2011
@@ -1059,39 +1059,53 @@
} else if (ReceiverType->isObjCClassType() ||
ReceiverType->isObjCQualifiedClassType()) {
// Handle messages to Class.
- if (ObjCMethodDecl *CurMeth = getCurMethodDecl()) {
- if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface()) {
- // First check the public methods in the class interface.
- Method = ClassDecl->lookupClassMethod(Sel);
-
- if (!Method)
- Method = LookupPrivateClassMethod(Sel, ClassDecl);
+ // We allow sending a message to a qualified Class ("Class<foo>"), which
+ // is ok as long as one of the protocols implements the selector (if not, warn).
+ if (const ObjCObjectPointerType *QClassTy
+ = ReceiverType->getAsObjCQualifiedClassType()) {
+ // Search protocols for class methods.
+ Method = LookupMethodInQualifiedType(Sel, QClassTy, false);
+ if (!Method) {
+ Method = LookupMethodInQualifiedType(Sel, QClassTy, true);
+ // warn if instance method found for a Class message.
+ if (Method) {
+ Diag(Loc, diag::warn_instance_method_on_class_found)
+ << Method->getSelector() << Sel;
+ Diag(Method->getLocation(), diag::note_method_declared_at);
+ }
+ }
+ } else {
+ if (ObjCMethodDecl *CurMeth = getCurMethodDecl()) {
+ if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface()) {
+ // First check the public methods in the class interface.
+ Method = ClassDecl->lookupClassMethod(Sel);
- // FIXME: if we still haven't found a method, we need to look in
- // protocols (if we have qualifiers).
+ if (!Method)
+ Method = LookupPrivateClassMethod(Sel, ClassDecl);
+ }
+ if (Method && DiagnoseUseOfDecl(Method, Loc))
+ return ExprError();
}
- if (Method && DiagnoseUseOfDecl(Method, Loc))
- return ExprError();
- }
- if (!Method) {
- // If not messaging 'self', look for any factory method named 'Sel'.
- if (!Receiver || !isSelfExpr(Receiver)) {
- Method = LookupFactoryMethodInGlobalPool(Sel,
- SourceRange(LBracLoc, RBracLoc),
- true);
- if (!Method) {
- // If no class (factory) method was found, check if an _instance_
- // method of the same name exists in the root class only.
- Method = LookupInstanceMethodInGlobalPool(Sel,
+ if (!Method) {
+ // If not messaging 'self', look for any factory method named 'Sel'.
+ if (!Receiver || !isSelfExpr(Receiver)) {
+ Method = LookupFactoryMethodInGlobalPool(Sel,
+ SourceRange(LBracLoc, RBracLoc),
+ true);
+ if (!Method) {
+ // If no class (factory) method was found, check if an _instance_
+ // method of the same name exists in the root class only.
+ Method = LookupInstanceMethodInGlobalPool(Sel,
SourceRange(LBracLoc, RBracLoc),
- true);
- if (Method)
- if (const ObjCInterfaceDecl *ID =
- dyn_cast<ObjCInterfaceDecl>(Method->getDeclContext())) {
- if (ID->getSuperClass())
- Diag(Loc, diag::warn_root_inst_method_not_found)
- << Sel << SourceRange(LBracLoc, RBracLoc);
- }
+ true);
+ if (Method)
+ if (const ObjCInterfaceDecl *ID =
+ dyn_cast<ObjCInterfaceDecl>(Method->getDeclContext())) {
+ if (ID->getSuperClass())
+ Diag(Loc, diag::warn_root_inst_method_not_found)
+ << Sel << SourceRange(LBracLoc, RBracLoc);
+ }
+ }
}
}
}
Added: cfe/trunk/test/SemaObjC/class-message-protocol-lookup.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/class-message-protocol-lookup.m?rev=129016&view=auto
==============================================================================
--- cfe/trunk/test/SemaObjC/class-message-protocol-lookup.m (added)
+++ cfe/trunk/test/SemaObjC/class-message-protocol-lookup.m Wed Apr 6 13:40:08 2011
@@ -0,0 +1,34 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+// rdar://9224670
+
+ at interface RandomObject {
+ at private
+}
++ (id)alloc;
+ at end
+
+ at protocol TestProtocol
+- (void)nothingInteresting;
+ at end
+
+ at protocol Test2Protocol
++ (id)alloc;
+- (id)alloc2; // expected-note 2 {{method declared here}}
+ at end
+
+ at implementation RandomObject
+- (void) Meth {
+ Class<TestProtocol> c = [c alloc]; // expected-warning {{class method '+alloc' not found (return type defaults to 'id')}}
+ Class<Test2Protocol> c1 = [c1 alloc2]; // expected-warning {{instance method 'alloc2' found instead of class method 'alloc2'}}
+ Class<Test2Protocol> c2 = [c2 alloc]; // ok
+}
++ (id)alloc { return 0; }
+ at end
+
+int main ()
+{
+ Class<TestProtocol> c = [c alloc]; // expected-warning {{class method '+alloc' not found (return type defaults to 'id')}}
+ Class<Test2Protocol> c1 = [c1 alloc2]; // expected-warning {{instance method 'alloc2' found instead of class method 'alloc2'}}
+ Class<Test2Protocol> c2 = [c2 alloc]; // ok
+ return 0;
+}
More information about the cfe-commits
mailing list