[cfe-commits] r78726 - in /cfe/trunk: include/clang/AST/ASTContext.h include/clang/AST/DeclObjC.h include/clang/Basic/DiagnosticSemaKinds.td lib/AST/ASTContext.cpp lib/AST/DeclObjC.cpp lib/Sema/SemaDeclObjC.cpp test/SemaObjC/warn-assign-property-nscopying.m
Fariborz Jahanian
fjahanian at apple.com
Tue Aug 11 15:02:25 PDT 2009
Author: fjahanian
Date: Tue Aug 11 17:02:25 2009
New Revision: 78726
URL: http://llvm.org/viewvc/llvm-project?rev=78726&view=rev
Log:
Patch to warn if a property which is 'assign' by default
may not implement NSCopying protocol in -fobjc-gc[-only] mode.
Added:
cfe/trunk/test/SemaObjC/warn-assign-property-nscopying.m
Modified:
cfe/trunk/include/clang/AST/ASTContext.h
cfe/trunk/include/clang/AST/DeclObjC.h
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/lib/AST/ASTContext.cpp
cfe/trunk/lib/AST/DeclObjC.cpp
cfe/trunk/lib/Sema/SemaDeclObjC.cpp
Modified: cfe/trunk/include/clang/AST/ASTContext.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=78726&r1=78725&r2=78726&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ASTContext.h (original)
+++ cfe/trunk/include/clang/AST/ASTContext.h Tue Aug 11 17:02:25 2009
@@ -557,6 +557,9 @@
const Decl *Container,
std::string &S);
+ bool ProtocolCompatibleWithProtocol(ObjCProtocolDecl *lProto,
+ ObjCProtocolDecl *rProto);
+
/// getObjCEncodingTypeSize returns size of type for objective-c encoding
/// purpose.
int getObjCEncodingTypeSize(QualType t);
Modified: cfe/trunk/include/clang/AST/DeclObjC.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclObjC.h?rev=78726&r1=78725&r2=78726&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclObjC.h (original)
+++ cfe/trunk/include/clang/AST/DeclObjC.h Tue Aug 11 17:02:25 2009
@@ -530,6 +530,13 @@
bool isImplicitInterfaceDecl() const { return InternalInterface; }
void setImplicitInterfaceDecl(bool val) { InternalInterface = val; }
+ /// ClassImplementsProtocol - Checks that 'lProto' protocol
+ /// has been implemented in IDecl class, its super class or categories (if
+ /// lookupCategory is true).
+ bool ClassImplementsProtocol(ObjCProtocolDecl *lProto,
+ bool lookupCategory,
+ bool RHSIsQualifiedID = false);
+
// Low-level accessor
Type *getTypeForDecl() const { return TypeForDecl; }
void setTypeForDecl(Type *TD) const { TypeForDecl = TD; }
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=78726&r1=78725&r2=78726&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Tue Aug 11 17:02:25 2009
@@ -221,6 +221,10 @@
def warn_conflicting_param_types : Warning<
"conflicting parameter types in implementation of %0: %1 vs %2">;
+def warn_implements_nscopying : Warning<
+"default assign attribute on property %0 which implements "
+"NSCopying protocol is not appropriate with -fobjc-gc[-only]">;
+
def warn_multiple_method_decl : Warning<"multiple methods named %0 found">;
def warn_accessor_property_type_mismatch : Warning<
"type of property %0 does not match type of accessor %1">;
Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=78726&r1=78725&r2=78726&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Tue Aug 11 17:02:25 2009
@@ -3290,8 +3290,8 @@
/// ProtocolCompatibleWithProtocol - return 'true' if 'lProto' is in the
/// inheritance hierarchy of 'rProto'.
-static bool ProtocolCompatibleWithProtocol(ObjCProtocolDecl *lProto,
- ObjCProtocolDecl *rProto) {
+bool ASTContext::ProtocolCompatibleWithProtocol(ObjCProtocolDecl *lProto,
+ ObjCProtocolDecl *rProto) {
if (lProto == rProto)
return true;
for (ObjCProtocolDecl::protocol_iterator PI = rProto->protocol_begin(),
@@ -3301,51 +3301,6 @@
return false;
}
-/// ClassImplementsProtocol - Checks that 'lProto' protocol
-/// has been implemented in IDecl class, its super class or categories (if
-/// lookupCategory is true).
-static bool ClassImplementsProtocol(ObjCProtocolDecl *lProto,
- ObjCInterfaceDecl *IDecl,
- bool lookupCategory,
- bool RHSIsQualifiedID = false) {
-
- // 1st, look up the class.
- const ObjCList<ObjCProtocolDecl> &Protocols =
- IDecl->getReferencedProtocols();
-
- for (ObjCList<ObjCProtocolDecl>::iterator PI = Protocols.begin(),
- E = Protocols.end(); PI != E; ++PI) {
- if (ProtocolCompatibleWithProtocol(lProto, *PI))
- return true;
- // This is dubious and is added to be compatible with gcc. In gcc, it is
- // also allowed assigning a protocol-qualified 'id' type to a LHS object
- // when protocol in qualified LHS is in list of protocols in the rhs 'id'
- // object. This IMO, should be a bug.
- // FIXME: Treat this as an extension, and flag this as an error when GCC
- // extensions are not enabled.
- if (RHSIsQualifiedID && ProtocolCompatibleWithProtocol(*PI, lProto))
- return true;
- }
-
- // 2nd, look up the category.
- if (lookupCategory)
- for (ObjCCategoryDecl *CDecl = IDecl->getCategoryList(); CDecl;
- CDecl = CDecl->getNextClassCategory()) {
- for (ObjCCategoryDecl::protocol_iterator PI = CDecl->protocol_begin(),
- E = CDecl->protocol_end(); PI != E; ++PI)
- if (ProtocolCompatibleWithProtocol(lProto, *PI))
- return true;
- }
-
- // 3rd, look up the super class(s)
- if (IDecl->getSuperClass())
- return
- ClassImplementsProtocol(lProto, IDecl->getSuperClass(), lookupCategory,
- RHSIsQualifiedID);
-
- return false;
-}
-
/// QualifiedIdConformsQualifiedId - compare id<p,...> with id<p1,...>
/// return true if lhs's protocols conform to rhs's protocol; false
/// otherwise.
@@ -3381,7 +3336,7 @@
// when comparing an id<P> on lhs with a static type on rhs,
// see if static class implements all of id's protocols, directly or
// through its super class and categories.
- if (!ClassImplementsProtocol(*I, rhsID, true))
+ if (!rhsID->ClassImplementsProtocol(*I, true))
return false;
}
}
@@ -3414,7 +3369,7 @@
// when comparing an id<P> on lhs with a static type on rhs,
// see if static class implements all of id's protocols, directly or
// through its super class and categories.
- if (ClassImplementsProtocol(*I, rhsID, true)) {
+ if (rhsID->ClassImplementsProtocol(*I, true)) {
match = true;
break;
}
@@ -3440,7 +3395,7 @@
// when comparing an id<P> on lhs with a static type on rhs,
// see if static class implements all of id's protocols, directly or
// through its super class and categories.
- if (ClassImplementsProtocol(*I, lhsID, true)) {
+ if (lhsID->ClassImplementsProtocol(*I, true)) {
match = true;
break;
}
Modified: cfe/trunk/lib/AST/DeclObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclObjC.cpp?rev=78726&r1=78725&r2=78726&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclObjC.cpp (original)
+++ cfe/trunk/lib/AST/DeclObjC.cpp Tue Aug 11 17:02:25 2009
@@ -398,6 +398,51 @@
return 0;
}
+/// ClassImplementsProtocol - Checks that 'lProto' protocol
+/// has been implemented in IDecl class, its super class or categories (if
+/// lookupCategory is true).
+bool ObjCInterfaceDecl::ClassImplementsProtocol(ObjCProtocolDecl *lProto,
+ bool lookupCategory,
+ bool RHSIsQualifiedID) {
+ ObjCInterfaceDecl *IDecl = this;
+ // 1st, look up the class.
+ const ObjCList<ObjCProtocolDecl> &Protocols =
+ IDecl->getReferencedProtocols();
+
+ for (ObjCList<ObjCProtocolDecl>::iterator PI = Protocols.begin(),
+ E = Protocols.end(); PI != E; ++PI) {
+ if (getASTContext().ProtocolCompatibleWithProtocol(lProto, *PI))
+ return true;
+ // This is dubious and is added to be compatible with gcc. In gcc, it is
+ // also allowed assigning a protocol-qualified 'id' type to a LHS object
+ // when protocol in qualified LHS is in list of protocols in the rhs 'id'
+ // object. This IMO, should be a bug.
+ // FIXME: Treat this as an extension, and flag this as an error when GCC
+ // extensions are not enabled.
+ if (RHSIsQualifiedID &&
+ getASTContext().ProtocolCompatibleWithProtocol(*PI, lProto))
+ return true;
+ }
+
+ // 2nd, look up the category.
+ if (lookupCategory)
+ for (ObjCCategoryDecl *CDecl = IDecl->getCategoryList(); CDecl;
+ CDecl = CDecl->getNextClassCategory()) {
+ for (ObjCCategoryDecl::protocol_iterator PI = CDecl->protocol_begin(),
+ E = CDecl->protocol_end(); PI != E; ++PI)
+ if (getASTContext().ProtocolCompatibleWithProtocol(lProto, *PI))
+ return true;
+ }
+
+ // 3rd, look up the super class(s)
+ if (IDecl->getSuperClass())
+ return
+ IDecl->getSuperClass()->ClassImplementsProtocol(lProto, lookupCategory,
+ RHSIsQualifiedID);
+
+ return false;
+}
+
//===----------------------------------------------------------------------===//
// ObjCIvarDecl
//===----------------------------------------------------------------------===//
Modified: cfe/trunk/lib/Sema/SemaDeclObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclObjC.cpp?rev=78726&r1=78725&r2=78726&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclObjC.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclObjC.cpp Tue Aug 11 17:02:25 2009
@@ -1924,7 +1924,23 @@
return DeclPtrTy();
}
}
-
+
+ // Issue a warning if property is 'assign' as default and its object, which is
+ // gc'able conforms to NSCopying protocol
+ if (getLangOptions().getGCMode() != LangOptions::NonGC &&
+ isAssign && !(Attributes & ObjCDeclSpec::DQ_PR_assign))
+ if (T->isObjCObjectPointerType()) {
+ QualType InterfaceTy = T->getPointeeType();
+ ObjCInterfaceDecl *IDecl=
+ InterfaceTy->getAsObjCInterfaceType()->getDecl();
+ if (IDecl)
+ if (ObjCProtocolDecl* PNSCopying =
+ LookupProtocol(&Context.Idents.get("NSCopying")))
+ if (IDecl->ClassImplementsProtocol(PNSCopying, true))
+ Diag(AtLoc, diag::warn_implements_nscopying)
+ << FD.D.getIdentifier();
+ }
+
DeclContext *DC = dyn_cast<DeclContext>(ClassDecl);
assert(DC && "ClassDecl is not a DeclContext");
ObjCPropertyDecl *PDecl = ObjCPropertyDecl::Create(Context, DC,
Added: cfe/trunk/test/SemaObjC/warn-assign-property-nscopying.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/warn-assign-property-nscopying.m?rev=78726&view=auto
==============================================================================
--- cfe/trunk/test/SemaObjC/warn-assign-property-nscopying.m (added)
+++ cfe/trunk/test/SemaObjC/warn-assign-property-nscopying.m Tue Aug 11 17:02:25 2009
@@ -0,0 +1,14 @@
+// RUN: clang-cc -fobjc-gc -fsyntax-only -verify %s
+
+ at protocol NSCopying @end
+
+ at interface NSObject <NSCopying>
+ at end
+
+ at interface NSDictionary : NSObject
+ at end
+
+ at interface INTF
+ @property NSDictionary* undoAction; // expected-warning {{no 'assign', 'retain', or 'copy' attribute is specified - 'assign' is assumed}} // expected-warning {{default assign attribute on property 'undoAction' which implements NSCopying protocol is not appropriate with}}
+ at end
+
More information about the cfe-commits
mailing list