[cfe-commits] r45263 - in /cfe/trunk: AST/ASTContext.cpp AST/Decl.cpp Sema/SemaDeclObjC.cpp include/clang/AST/DeclObjC.h test/Sema/objc-comptypes-1.m
Fariborz Jahanian
fjahanian at apple.com
Thu Dec 20 11:24:12 PST 2007
Author: fjahanian
Date: Thu Dec 20 13:24:10 2007
New Revision: 45263
URL: http://llvm.org/viewvc/llvm-project?rev=45263&view=rev
Log:
Patch to do type-checking for objctive-c's object types.
More is yet to come.
Added:
cfe/trunk/test/Sema/objc-comptypes-1.m
Modified:
cfe/trunk/AST/ASTContext.cpp
cfe/trunk/AST/Decl.cpp
cfe/trunk/Sema/SemaDeclObjC.cpp
cfe/trunk/include/clang/AST/DeclObjC.h
Modified: cfe/trunk/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/AST/ASTContext.cpp?rev=45263&r1=45262&r2=45263&view=diff
==============================================================================
--- cfe/trunk/AST/ASTContext.cpp (original)
+++ cfe/trunk/AST/ASTContext.cpp Thu Dec 20 13:24:10 2007
@@ -1273,19 +1273,21 @@
// match id<P..> with an 'id' type in all cases.
if (const PointerType *PT = lhs->getAsPointerType()) {
QualType PointeeTy = PT->getPointeeType();
- if (isObjcIdType(PointeeTy))
+ if (isObjcIdType(PointeeTy) || PointeeTy->isVoidType())
return true;
}
else if (const PointerType *PT = rhs->getAsPointerType()) {
QualType PointeeTy = PT->getPointeeType();
- if (isObjcIdType(PointeeTy))
+ if (isObjcIdType(PointeeTy) || PointeeTy->isVoidType())
return true;
}
ObjcQualifiedInterfaceType *lhsQI = 0;
ObjcQualifiedInterfaceType *rhsQI = 0;
+ ObjcInterfaceDecl *lhsID = 0;
+ ObjcInterfaceDecl *rhsID = 0;
ObjcQualifiedIdType *lhsQID = dyn_cast<ObjcQualifiedIdType>(lhs);
ObjcQualifiedIdType *rhsQID = dyn_cast<ObjcQualifiedIdType>(rhs);
@@ -1296,8 +1298,14 @@
rhsQI =
dyn_cast<ObjcQualifiedInterfaceType>(
rtype.getCanonicalType().getTypePtr());
+ if (!rhsQI) {
+ ObjcInterfaceType *IT = dyn_cast<ObjcInterfaceType>(
+ rtype.getCanonicalType().getTypePtr());
+ if (IT)
+ rhsID = IT->getDecl();
+ }
}
- if (!rhsQI && !rhsQID)
+ if (!rhsQI && !rhsQID && !rhsID)
return false;
for (unsigned i =0; i < lhsQID->getNumProtocols(); i++) {
@@ -1309,10 +1317,14 @@
numRhsProtocols = rhsQI->getNumProtocols();
rhsProtoList = rhsQI->getReferencedProtocols();
}
- else {
+ else if (rhsQID) {
numRhsProtocols = rhsQID->getNumProtocols();
rhsProtoList = rhsQID->getReferencedProtocols();
}
+ else {
+ numRhsProtocols = rhsID->getNumIntfRefProtocols();
+ rhsProtoList = rhsID->getReferencedProtocols();
+ }
for (unsigned j = 0; j < numRhsProtocols; j++) {
ObjcProtocolDecl *rhsProto = rhsProtoList[j];
if (lhsProto == rhsProto) {
@@ -1331,19 +1343,31 @@
lhsQI =
dyn_cast<ObjcQualifiedInterfaceType>(
ltype.getCanonicalType().getTypePtr());
+ if (!lhsQI) {
+ ObjcInterfaceType *IT = dyn_cast<ObjcInterfaceType>(
+ ltype.getCanonicalType().getTypePtr());
+ if (IT)
+ lhsID = IT->getDecl();
+ }
}
- if (!lhsQI && !lhsQID)
+ if (!lhsQI && !lhsQID && !lhsID)
return false;
+
unsigned numLhsProtocols;
ObjcProtocolDecl **lhsProtoList;
if (lhsQI) {
numLhsProtocols = lhsQI->getNumProtocols();
lhsProtoList = lhsQI->getReferencedProtocols();
}
- else {
+ else if (lhsQID) {
numLhsProtocols = lhsQID->getNumProtocols();
lhsProtoList = lhsQID->getReferencedProtocols();
}
+ else {
+ numLhsProtocols = lhsID->getNumIntfRefProtocols();
+ lhsProtoList = lhsID->getReferencedProtocols();
+ }
+
for (unsigned i =0; i < numLhsProtocols; i++) {
bool match = false;
ObjcProtocolDecl *lhsProto = lhsProtoList[i];
Modified: cfe/trunk/AST/Decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/AST/Decl.cpp?rev=45263&r1=45262&r2=45263&view=diff
==============================================================================
--- cfe/trunk/AST/Decl.cpp (original)
+++ cfe/trunk/AST/Decl.cpp Thu Dec 20 13:24:10 2007
@@ -516,7 +516,7 @@
if (getNumReferencedProtocols() > 0) {
ObjcProtocolDecl **RefPDecl = getReferencedProtocols();
- for (int i = 0; i < getNumReferencedProtocols(); i++) {
+ for (unsigned i = 0; i < getNumReferencedProtocols(); i++) {
if ((MethodDecl = RefPDecl[i]->getInstanceMethod(Sel)))
return MethodDecl;
}
@@ -535,7 +535,7 @@
if (getNumReferencedProtocols() > 0) {
ObjcProtocolDecl **RefPDecl = getReferencedProtocols();
- for (int i = 0; i < getNumReferencedProtocols(); i++) {
+ for(unsigned i = 0; i < getNumReferencedProtocols(); i++) {
if ((MethodDecl = RefPDecl[i]->getClassMethod(Sel)))
return MethodDecl;
}
Modified: cfe/trunk/Sema/SemaDeclObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Sema/SemaDeclObjC.cpp?rev=45263&r1=45262&r2=45263&view=diff
==============================================================================
--- cfe/trunk/Sema/SemaDeclObjC.cpp (original)
+++ cfe/trunk/Sema/SemaDeclObjC.cpp Thu Dec 20 13:24:10 2007
@@ -135,7 +135,7 @@
Diag(ClassLoc, diag::warn_undef_protocolref,
ProtocolNames[i]->getName(),
ClassName->getName());
- IDecl->setIntfRefProtocols((int)i, RefPDecl);
+ IDecl->setIntfRefProtocols(i, RefPDecl);
}
IDecl->setLocEnd(EndProtoLoc);
}
@@ -216,7 +216,7 @@
Diag(ProtocolLoc, diag::warn_undef_protocolref,
ProtoRefNames[i]->getName(),
ProtocolName->getName());
- PDecl->setReferencedProtocols((int)i, RefPDecl);
+ PDecl->setReferencedProtocols(i, RefPDecl);
}
PDecl->setLocEnd(EndProtoLoc);
}
@@ -300,7 +300,7 @@
ProtoRefNames[i]->getName(),
CategoryName->getName());
}
- CDecl->setCatReferencedProtocols((int)i, RefPDecl);
+ CDecl->setCatReferencedProtocols(i, RefPDecl);
}
CDecl->setLocEnd(EndProtoLoc);
}
@@ -481,7 +481,7 @@
}
// Check on this protocols's referenced protocols, recursively
ObjcProtocolDecl** RefPDecl = PDecl->getReferencedProtocols();
- for (int i = 0; i < PDecl->getNumReferencedProtocols(); i++)
+ for (unsigned i = 0; i < PDecl->getNumReferencedProtocols(); i++)
CheckProtocolMethodDefs(RefPDecl[i], IncompleteImpl, InsMap, ClsMap);
}
@@ -521,7 +521,7 @@
// Check the protocol list for unimplemented methods in the @implementation
// class.
ObjcProtocolDecl** protocols = IDecl->getReferencedProtocols();
- for (int i = 0; i < IDecl->getNumIntfRefProtocols(); i++)
+ for (unsigned i = 0; i < IDecl->getNumIntfRefProtocols(); i++)
CheckProtocolMethodDefs(protocols[i], IncompleteImpl, InsMap, ClsMap);
if (IncompleteImpl)
@@ -567,7 +567,7 @@
// Check the protocol list for unimplemented methods in the @implementation
// class.
ObjcProtocolDecl** protocols = CatClassDecl->getReferencedProtocols();
- for (int i = 0; i < CatClassDecl->getNumReferencedProtocols(); i++) {
+ for (unsigned i = 0; i < CatClassDecl->getNumReferencedProtocols(); i++) {
ObjcProtocolDecl* PDecl = protocols[i];
CheckProtocolMethodDefs(PDecl, IncompleteImpl, InsMap, ClsMap);
}
Modified: cfe/trunk/include/clang/AST/DeclObjC.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclObjC.h?rev=45263&r1=45262&r2=45263&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclObjC.h (original)
+++ cfe/trunk/include/clang/AST/DeclObjC.h Thu Dec 20 13:24:10 2007
@@ -186,7 +186,7 @@
/// Protocols referenced in interface header declaration
ObjcProtocolDecl **ReferencedProtocols; // Null if none
- int NumReferencedProtocols; // -1 if none
+ unsigned NumReferencedProtocols; // 0 if none
/// Ivars/NumIvars - This is a new[]'d array of pointers to Decls.
ObjcIvarDecl **Ivars; // Null if not defined.
@@ -217,7 +217,7 @@
IdentifierInfo *Id, bool FD = false,
bool isInternal = false)
: TypeDecl(ObjcInterface, atLoc, Id, 0), SuperClass(0),
- ReferencedProtocols(0), NumReferencedProtocols(-1), Ivars(0),
+ ReferencedProtocols(0), NumReferencedProtocols(0), Ivars(0),
NumIvars(-1),
InstanceMethods(0), NumInstanceMethods(-1),
ClassMethods(0), NumClassMethods(-1),
@@ -239,7 +239,7 @@
ObjcProtocolDecl **getReferencedProtocols() const {
return ReferencedProtocols;
}
- int getNumIntfRefProtocols() const { return NumReferencedProtocols; }
+ unsigned getNumIntfRefProtocols() const { return NumReferencedProtocols; }
int getNumInstanceVariables() const { return NumIvars; }
@@ -273,7 +273,7 @@
bool isForwardDecl() const { return ForwardDecl; }
void setForwardDecl(bool val) { ForwardDecl = val; }
- void setIntfRefProtocols(int idx, ObjcProtocolDecl *OID) {
+ void setIntfRefProtocols(unsigned idx, ObjcProtocolDecl *OID) {
assert((idx < NumReferencedProtocols) && "index out of range");
ReferencedProtocols[idx] = OID;
}
@@ -394,7 +394,7 @@
class ObjcProtocolDecl : public NamedDecl {
/// referenced protocols
ObjcProtocolDecl **ReferencedProtocols; // Null if none
- int NumReferencedProtocols; // -1 if none
+ unsigned NumReferencedProtocols; // 0 if none
/// protocol instance methods
ObjcMethodDecl **InstanceMethods; // Null if not defined
@@ -412,7 +412,7 @@
ObjcProtocolDecl(SourceLocation L, unsigned numRefProtos,
IdentifierInfo *Id, bool FD = false)
: NamedDecl(ObjcProtocol, L, Id),
- ReferencedProtocols(0), NumReferencedProtocols(-1),
+ ReferencedProtocols(0), NumReferencedProtocols(0),
InstanceMethods(0), NumInstanceMethods(-1),
ClassMethods(0), NumClassMethods(-1),
isForwardProtoDecl(FD) {
@@ -430,7 +430,7 @@
ObjcMethodDecl **clsMethods, unsigned numClsMembers,
SourceLocation AtEndLoc);
- void setReferencedProtocols(int idx, ObjcProtocolDecl *OID) {
+ void setReferencedProtocols(unsigned idx, ObjcProtocolDecl *OID) {
assert((idx < NumReferencedProtocols) && "index out of range");
ReferencedProtocols[idx] = OID;
}
@@ -438,7 +438,7 @@
ObjcProtocolDecl** getReferencedProtocols() const {
return ReferencedProtocols;
}
- int getNumReferencedProtocols() const { return NumReferencedProtocols; }
+ unsigned getNumReferencedProtocols() const { return NumReferencedProtocols; }
int getNumInstanceMethods() const { return NumInstanceMethods; }
int getNumClassMethods() const { return NumClassMethods; }
@@ -587,7 +587,7 @@
/// referenced protocols in this category
ObjcProtocolDecl **ReferencedProtocols; // Null if none
- int NumReferencedProtocols; // -1 if none
+ unsigned NumReferencedProtocols; // 0 if none
/// category instance methods
ObjcMethodDecl **InstanceMethods; // Null if not defined
@@ -605,7 +605,7 @@
public:
ObjcCategoryDecl(SourceLocation L, unsigned numRefProtocol,IdentifierInfo *Id)
: NamedDecl(ObjcCategory, L, Id),
- ClassInterface(0), ReferencedProtocols(0), NumReferencedProtocols(-1),
+ ClassInterface(0), ReferencedProtocols(0), NumReferencedProtocols(0),
InstanceMethods(0), NumInstanceMethods(-1),
ClassMethods(0), NumClassMethods(-1),
NextClassCategory(0) {
@@ -620,7 +620,7 @@
ObjcInterfaceDecl *getClassInterface() const { return ClassInterface; }
void setClassInterface(ObjcInterfaceDecl *IDecl) { ClassInterface = IDecl; }
- void setCatReferencedProtocols(int idx, ObjcProtocolDecl *OID) {
+ void setCatReferencedProtocols(unsigned idx, ObjcProtocolDecl *OID) {
assert((idx < NumReferencedProtocols) && "index out of range");
ReferencedProtocols[idx] = OID;
}
@@ -628,7 +628,7 @@
ObjcProtocolDecl **getReferencedProtocols() const {
return ReferencedProtocols;
}
- int getNumReferencedProtocols() const { return NumReferencedProtocols; }
+ unsigned getNumReferencedProtocols() const { return NumReferencedProtocols; }
int getNumInstanceMethods() const { return NumInstanceMethods; }
int getNumClassMethods() const { return NumClassMethods; }
Added: cfe/trunk/test/Sema/objc-comptypes-1.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/objc-comptypes-1.m?rev=45263&view=auto
==============================================================================
--- cfe/trunk/test/Sema/objc-comptypes-1.m (added)
+++ cfe/trunk/test/Sema/objc-comptypes-1.m Thu Dec 20 13:24:10 2007
@@ -0,0 +1,82 @@
+// RUN: clang -fsyntax-only -verify %s
+
+#include <objc/objc.h>
+
+extern void foo();
+
+ at protocol MyProtocol
+- (void) foo;
+ at end
+
+ at interface MyClass
+ at end
+
+ at interface MyOtherClass <MyProtocol>
+- (void) foo;
+ at end
+
+int main()
+{
+ id obj = nil;
+ id<MyProtocol> obj_p = nil;
+ MyClass *obj_c = nil;
+ MyOtherClass *obj_cp = nil;
+ Class obj_C = Nil;
+
+ /* Assigning to an 'id' variable should never
+ generate a warning. */
+ obj = obj_p; /* Ok */
+ obj = obj_c; /* Ok */
+ obj = obj_cp; /* Ok */
+ obj = obj_C; /* Ok */
+
+ /* Assigning to a 'MyClass *' variable should always generate a
+ warning, unless done from an 'id'. */
+ obj_c = obj; /* Ok */
+ obj_c = obj_C; // expected-warning {{incompatible pointer types assigning 'Class' to 'MyClass *'}}
+
+ /* Assigning to an 'id<MyProtocol>' variable should generate a
+ warning if done from a 'MyClass *' (which doesn't implement
+ MyProtocol), but not from an 'id' or from a 'MyOtherClass *'
+ (which implements MyProtocol). */
+ obj_p = obj; /* Ok */
+ obj_p = obj_c; // expected-error {{incompatible types assigning 'MyClass *' to 'id<MyProtocol>'}}
+ obj_p = obj_cp; /* Ok */
+ obj_p = obj_C; // expected-error {{incompatible types assigning 'Class' to 'id<MyProtocol>'}}
+
+ /* Assigning to a 'MyOtherClass *' variable should always generate
+ a warning, unless done from an 'id' or an 'id<MyProtocol>' (since
+ MyOtherClass implements MyProtocol). */
+ obj_cp = obj; /* Ok */
+ obj_cp = obj_p; /* Ok */
+ obj_cp = obj_C; // expected-warning {{incompatible pointer types assigning 'Class' to 'MyOtherClass *'}}
+
+ /* Any comparison involving an 'id' must be without warnings. */
+ if (obj == obj_p) foo() ; /* Ok */ /*Bogus warning here in 2.95.4*/
+ if (obj_p == obj) foo() ; /* Ok */
+ if (obj == obj_c) foo() ; /* Ok */
+ if (obj_c == obj) foo() ; /* Ok */
+ if (obj == obj_cp) foo() ; /* Ok */
+ if (obj_cp == obj) foo() ; /* Ok */
+ if (obj == obj_C) foo() ; /* Ok */
+ if (obj_C == obj) foo() ; /* Ok */
+
+ /* Any comparison between 'MyClass *' and anything which is not an 'id'
+ must generate a warning. */
+ if (obj_p == obj_c) foo() ; // expected-error {{invalid operands to binary expression ('id<MyProtocol>' and 'MyClass *')}}
+ if (obj_c == obj_C) foo() ; // expected-warning {{comparison of distinct pointer types ('MyClass *' and 'Class')}}
+ if (obj_C == obj_c) foo() ; // expected-warning {{comparison of distinct pointer types ('Class' and 'MyClass *')}}
+
+ /* Any comparison between 'MyOtherClass *' (which implements
+ MyProtocol) and an 'id' implementing MyProtocol are Ok. */
+ if (obj_cp == obj_p) foo() ; /* Ok */
+ if (obj_p == obj_cp) foo() ; /* Ok */
+
+
+ if (obj_p == obj_C) foo() ; // expected-error {{invalid operands to binary expression ('id<MyProtocol>' and 'Class')}}
+ if (obj_C == obj_p) foo() ; // expected-error {{invalid operands to binary expression ('Class' and 'id<MyProtocol>')}}
+ if (obj_cp == obj_C) foo() ; // expected-warning {{comparison of distinct pointer types ('MyOtherClass *' and 'Class')}}
+ if (obj_C == obj_cp) foo() ; // expected-warning {{comparison of distinct pointer types ('Class' and 'MyOtherClass *')}}
+
+ return 0;
+}
More information about the cfe-commits
mailing list