[cfe-commits] r56507 - in /cfe/trunk: include/clang/Basic/DiagnosticKinds.def lib/Sema/Sema.h lib/Sema/SemaDeclObjC.cpp test/SemaObjC/property-1.m test/SemaObjC/property-10.m
Daniel Dunbar
daniel at zuster.org
Tue Sep 23 14:53:23 PDT 2008
Author: ddunbar
Date: Tue Sep 23 16:53:23 2008
New Revision: 56507
URL: http://llvm.org/viewvc/llvm-project?rev=56507&view=rev
Log:
Implement type checking of Objective-C property attributes.
- readonly and readwrite are mutually exclusive.
- assign, copy, and retain are mutually exclusive.
- copy and retain are invalid on non-object types.
- Warn about using default 'assign' property on object types
(attempting to follow gcc behavior).
Added:
cfe/trunk/test/SemaObjC/property-10.m
Modified:
cfe/trunk/include/clang/Basic/DiagnosticKinds.def
cfe/trunk/lib/Sema/Sema.h
cfe/trunk/lib/Sema/SemaDeclObjC.cpp
cfe/trunk/test/SemaObjC/property-1.m
Modified: cfe/trunk/include/clang/Basic/DiagnosticKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticKinds.def?rev=56507&r1=56506&r2=56507&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticKinds.def Tue Sep 23 16:53:23 2008
@@ -421,6 +421,14 @@
"setter/getter expects '=' followed by name")
DIAG(err_objc_expected_property_attr, ERROR,
"unknown property attribute detected")
+DIAG(err_objc_property_attr_mutually_exclusive, ERROR,
+ "property attributes '%0' and '%1' are mutually exclusive")
+DIAG(warn_objc_property_no_assignment_attribute, WARNING,
+ "no 'assign', 'retain', or 'copy' attribute is specified - 'assign' is assumed")
+DIAG(warn_objc_property_default_assign_on_object, WARNING,
+ "default property attribute 'assign' not appropriate for non-gc object")
+DIAG(err_objc_property_requires_object, ERROR,
+ "property with '%0' attribute must be of object type")
DIAG(err_objc_protocol_required, ERROR,
"@required may be specified in protocols only")
DIAG(err_objc_protocol_optional, ERROR,
Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=56507&r1=56506&r2=56507&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Tue Sep 23 16:53:23 2008
@@ -723,6 +723,12 @@
unsigned NumProtocols,
llvm::SmallVectorImpl<DeclTy *> &Protocols);
+ /// Ensure attributes are consistent with type.
+ /// \param [in, out] Attributes The attributes to check; they will
+ /// be modified to be consistent with \arg PropertyTy.
+ void CheckObjCPropertyAttributes(QualType PropertyTy,
+ SourceLocation Loc,
+ unsigned &Attributes);
void DiagnosePropertyMismatch(ObjCPropertyDecl *Property,
ObjCPropertyDecl *SuperProperty,
const char *Name);
Modified: cfe/trunk/lib/Sema/SemaDeclObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclObjC.cpp?rev=56507&r1=56506&r2=56507&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclObjC.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclObjC.cpp Tue Sep 23 16:53:23 2008
@@ -1038,6 +1038,68 @@
return ObjCMethod;
}
+void Sema::CheckObjCPropertyAttributes(QualType PropertyTy,
+ SourceLocation Loc,
+ unsigned &Attributes) {
+ // FIXME: Improve the reported location.
+
+ // readonly and readwrite conflict.
+ if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
+ (Attributes & ObjCDeclSpec::DQ_PR_readwrite)) {
+ Diag(Loc, diag::err_objc_property_attr_mutually_exclusive,
+ "readonly", "readwrite");
+ Attributes ^= ObjCDeclSpec::DQ_PR_readonly;
+ }
+
+ // Check for copy or retain on non-object types.
+ if ((Attributes & (ObjCDeclSpec::DQ_PR_copy | ObjCDeclSpec::DQ_PR_retain)) &&
+ !Context.isObjCObjectPointerType(PropertyTy)) {
+ Diag(Loc, diag::err_objc_property_requires_object,
+ Attributes & ObjCDeclSpec::DQ_PR_copy ? "copy" : "retain");
+ Attributes &= ~(ObjCDeclSpec::DQ_PR_copy | ObjCDeclSpec::DQ_PR_retain);
+ }
+
+ // Check for more than one of { assign, copy, retain }.
+ if (Attributes & ObjCDeclSpec::DQ_PR_assign) {
+ if (Attributes & ObjCDeclSpec::DQ_PR_copy) {
+ Diag(Loc, diag::err_objc_property_attr_mutually_exclusive,
+ "assign", "copy");
+ Attributes ^= ObjCDeclSpec::DQ_PR_copy;
+ }
+ if (Attributes & ObjCDeclSpec::DQ_PR_retain) {
+ Diag(Loc, diag::err_objc_property_attr_mutually_exclusive,
+ "assign", "retain");
+ Attributes ^= ObjCDeclSpec::DQ_PR_retain;
+ }
+ } else if (Attributes & ObjCDeclSpec::DQ_PR_copy) {
+ if (Attributes & ObjCDeclSpec::DQ_PR_retain) {
+ Diag(Loc, diag::err_objc_property_attr_mutually_exclusive,
+ "copy", "retain");
+ Attributes ^= ObjCDeclSpec::DQ_PR_retain;
+ }
+ }
+
+ // Warn if user supplied no assignment attribute, property is
+ // readwrite, and this is an object type.
+ if (!(Attributes & (ObjCDeclSpec::DQ_PR_assign | ObjCDeclSpec::DQ_PR_copy |
+ ObjCDeclSpec::DQ_PR_retain)) &&
+ !(Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
+ Context.isObjCObjectPointerType(PropertyTy)) {
+ // Skip this warning in gc-only mode.
+ if (getLangOptions().getGCMode() != LangOptions::GCOnly)
+ Diag(Loc, diag::warn_objc_property_no_assignment_attribute);
+
+ // If non-gc code warn that this is likely inappropriate.
+ if (getLangOptions().getGCMode() == LangOptions::NonGC)
+ Diag(Loc, diag::warn_objc_property_default_assign_on_object);
+
+ // FIXME: Implement warning dependent on NSCopying being
+ // implemented. See also:
+ // <rdar://5168496&4855821&5607453&5096644&4947311&5698469&4947014&5168496>
+ // (please trim this list while you are at it).
+ }
+}
+
Sema::DeclTy *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc,
FieldDeclarator &FD,
ObjCDeclSpec &ODS,
@@ -1045,6 +1107,11 @@
Selector SetterSel,
tok::ObjCKeywordKind MethodImplKind) {
QualType T = GetTypeForDeclarator(FD.D, S);
+ unsigned Attributes = ODS.getPropertyAttributes();
+
+ // May modify Attributes.
+ CheckObjCPropertyAttributes(T, AtLoc, Attributes);
+
ObjCPropertyDecl *PDecl = ObjCPropertyDecl::Create(Context, AtLoc,
FD.D.getIdentifier(), T);
// Regardless of setter/getter attribute, we save the default getter/setter
@@ -1052,28 +1119,28 @@
PDecl->setGetterName(GetterSel);
PDecl->setSetterName(SetterSel);
- if (ODS.getPropertyAttributes() & ObjCDeclSpec::DQ_PR_readonly)
+ if (Attributes & ObjCDeclSpec::DQ_PR_readonly)
PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readonly);
- if (ODS.getPropertyAttributes() & ObjCDeclSpec::DQ_PR_getter)
+ if (Attributes & ObjCDeclSpec::DQ_PR_getter)
PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_getter);
- if (ODS.getPropertyAttributes() & ObjCDeclSpec::DQ_PR_setter)
+ if (Attributes & ObjCDeclSpec::DQ_PR_setter)
PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_setter);
- if (ODS.getPropertyAttributes() & ObjCDeclSpec::DQ_PR_assign)
+ if (Attributes & ObjCDeclSpec::DQ_PR_assign)
PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_assign);
- if (ODS.getPropertyAttributes() & ObjCDeclSpec::DQ_PR_readwrite)
+ if (Attributes & ObjCDeclSpec::DQ_PR_readwrite)
PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readwrite);
- if (ODS.getPropertyAttributes() & ObjCDeclSpec::DQ_PR_retain)
+ if (Attributes & ObjCDeclSpec::DQ_PR_retain)
PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_retain);
- if (ODS.getPropertyAttributes() & ObjCDeclSpec::DQ_PR_copy)
+ if (Attributes & ObjCDeclSpec::DQ_PR_copy)
PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_copy);
- if (ODS.getPropertyAttributes() & ObjCDeclSpec::DQ_PR_nonatomic)
+ if (Attributes & ObjCDeclSpec::DQ_PR_nonatomic)
PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_nonatomic);
if (MethodImplKind == tok::objc_required)
@@ -1116,7 +1183,7 @@
// Look for this property declaration in the @implementation's @interface
property = IDecl->FindPropertyDeclaration(PropertyId);
if (!property) {
- Diag(PropertyLoc, diag::error_bad_property_decl, IDecl->getName());
+ Diag(PropertyLoc, diag::error_bad_property_decl, IDecl->getName());
return 0;
}
}
Modified: cfe/trunk/test/SemaObjC/property-1.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/property-1.m?rev=56507&r1=56506&r2=56507&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/property-1.m (original)
+++ cfe/trunk/test/SemaObjC/property-1.m Tue Sep 23 16:53:23 2008
@@ -6,7 +6,7 @@
int name;
}
@property int d1;
- at property id prop_id;
+ at property id prop_id; // expected-warning {{no 'assign', 'retain', or 'copy' attribute is specified - 'assign' is assumed}}, expected-warning {{default property attribute 'assign' not appropriate for non-gc object}}
@property int name;
@end
Added: cfe/trunk/test/SemaObjC/property-10.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/property-10.m?rev=56507&view=auto
==============================================================================
--- cfe/trunk/test/SemaObjC/property-10.m (added)
+++ cfe/trunk/test/SemaObjC/property-10.m Tue Sep 23 16:53:23 2008
@@ -0,0 +1,18 @@
+// RUN: clang -fsyntax-only -verify %s
+
+// Check property attribute consistency.
+
+ at interface I0
+ at property(readonly, readwrite) int p0; // expected-error {{property attributes 'readonly' and 'readwrite' are mutually exclusive}}
+
+ at property(retain) int p1; // expected-error {{property with 'retain' attribute must be of object type}}
+
+ at property(copy) int p2; // expected-error {{property with 'copy' attribute must be of object type}}
+
+ at property(assign, copy) id p3_0; // expected-error {{property attributes 'assign' and 'copy' are mutually exclusive}}
+ at property(assign, retain) id p3_1; // expected-error {{property attributes 'assign' and 'retain' are mutually exclusive}}
+ at property(copy, retain) id p3_2; // expected-error {{property attributes 'copy' and 'retain' are mutually exclusive}}
+ at property(assign, copy, retain) id p3_3; // expected-error {{property attributes 'assign' and 'copy' are mutually exclusive}}, expected-error {{property attributes 'assign' and 'retain' are mutually exclusive}}
+
+ at property id p4; // expected-warning {{no 'assign', 'retain', or 'copy' attribute is specified - 'assign' is assumed}}, expected-warning {{default property attribute 'assign' not appropriate for non-gc object}}
+ at end
More information about the cfe-commits
mailing list