objective-C: Change rules for overriding properties in

class extensions a little. clang now allows readonly property 
with no ownership rule (assign, unsafe_unretained, weak, retain, 
strong, or copy) with a readwrite property with an ownership rule.
// rdar://12103400 


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@162319 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Fariborz Jahanian 2012-08-21 21:45:58 +00:00
parent c568e2f801
commit dad633b0a0
3 changed files with 76 additions and 15 deletions

View File

@ -102,6 +102,15 @@ static void checkARCPropertyDecl(Sema &S, ObjCPropertyDecl *property) {
<< propertyLifetime;
}
static unsigned deduceWeakPropertyFromType(Sema &S, QualType T) {
if ((S.getLangOpts().getGC() != LangOptions::NonGC &&
T.isObjCGCWeak()) ||
(S.getLangOpts().ObjCAutoRefCount &&
T.getObjCLifetime() == Qualifiers::OCL_Weak))
return ObjCDeclSpec::DQ_PR_weak;
return 0;
}
Decl *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc,
SourceLocation LParenLoc,
FieldDeclarator &FD,
@ -114,12 +123,8 @@ Decl *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc,
unsigned Attributes = ODS.getPropertyAttributes();
TypeSourceInfo *TSI = GetTypeForDeclarator(FD.D, S);
QualType T = TSI->getType();
if ((getLangOpts().getGC() != LangOptions::NonGC &&
T.isObjCGCWeak()) ||
(getLangOpts().ObjCAutoRefCount &&
T.getObjCLifetime() == Qualifiers::OCL_Weak))
Attributes |= ObjCDeclSpec::DQ_PR_weak;
Attributes |= deduceWeakPropertyFromType(*this, T);
bool isReadWrite = ((Attributes & ObjCDeclSpec::DQ_PR_readwrite) ||
// default is readwrite!
!(Attributes & ObjCDeclSpec::DQ_PR_readonly));
@ -236,6 +241,15 @@ static bool LocPropertyAttribute( ASTContext &Context, const char *attrName,
}
static unsigned getMemoryModel(unsigned attr) {
return attr & (ObjCPropertyDecl::OBJC_PR_assign |
ObjCPropertyDecl::OBJC_PR_retain |
ObjCPropertyDecl::OBJC_PR_copy |
ObjCPropertyDecl::OBJC_PR_weak |
ObjCPropertyDecl::OBJC_PR_strong |
ObjCPropertyDecl::OBJC_PR_unsafe_unretained);
}
Decl *
Sema::HandlePropertyInClassExtension(Scope *S,
SourceLocation AtLoc,
@ -342,13 +356,11 @@ Sema::HandlePropertyInClassExtension(Scope *S,
// with continuation class's readwrite property attribute!
unsigned PIkind = PIDecl->getPropertyAttributesAsWritten();
if (isReadWrite && (PIkind & ObjCPropertyDecl::OBJC_PR_readonly)) {
unsigned retainCopyNonatomic =
(ObjCPropertyDecl::OBJC_PR_retain |
ObjCPropertyDecl::OBJC_PR_strong |
ObjCPropertyDecl::OBJC_PR_copy |
ObjCPropertyDecl::OBJC_PR_nonatomic);
if ((Attributes & retainCopyNonatomic) !=
(PIkind & retainCopyNonatomic)) {
PIkind |= deduceWeakPropertyFromType(*this, PIDecl->getType());
unsigned ClassExtensionMemoryModel = getMemoryModel(Attributes);
unsigned PrimaryClassMemoryModel = getMemoryModel(PIkind);
if (PrimaryClassMemoryModel && ClassExtensionMemoryModel &&
(PrimaryClassMemoryModel != ClassExtensionMemoryModel)) {
Diag(AtLoc, diag::warn_property_attr_mismatch);
Diag(PIDecl->getLocation(), diag::note_property_declare);
}

View File

@ -5,13 +5,13 @@
id _object;
id _object1;
}
@property(readonly) id object; // expected-note {{property declared here}}
@property(readonly) id object;
@property(readwrite, assign) id object1; // expected-note {{property declared here}}
@property (readonly) int indentLevel;
@end
@interface ReadOnly ()
@property(readwrite, copy) id object; // expected-warning {{property attribute in class extension does not match the primary class}}
@property(readwrite, copy) id object; // Ok. declaring memory model in class extension - primary has none.
@property(readonly) id object1; // expected-error {{illegal redeclaration of property in class extension 'ReadOnly' (attribute must be 'readwrite', while its primary must be 'readonly')}}
@property (readwrite, assign) int indentLevel; // OK. assign the default in any case.
@end

View File

@ -0,0 +1,49 @@
// RUN: %clang_cc1 -fsyntax-only -verify -Weverything %s
// RUN: %clang_cc1 -x objective-c++ -fsyntax-only -verify -Weverything %s
// rdar://12103400
@class NSString;
@interface MyClass
@property (nonatomic, readonly) NSString* addingMemoryModel;
@property (nonatomic, copy, readonly) NSString* matchingMemoryModel;
@property (nonatomic, retain, readonly) NSString* addingNoNewMemoryModel;
@property (readonly) NSString* none;
@property (readonly) NSString* none1;
@property (assign, readonly) NSString* changeMemoryModel; // expected-note {{property declared here}}
@property (readonly) __weak id weak_prop;
@property (readonly) __weak id weak_prop1;
@property (assign, readonly) NSString* assignProperty;
@property (readonly) NSString* readonlyProp;
@end
@interface MyClass ()
{
NSString* _name;
}
@property (nonatomic, copy) NSString* addingMemoryModel;
@property (nonatomic, copy) NSString* matchingMemoryModel;
@property () NSString* addingNoNewMemoryModel;
@property () NSString* none;
@property (readwrite) NSString* none1;
@property (retain) NSString* changeMemoryModel; // expected-warning {{property attribute in class extension does not match the primary class}}
@property () __weak id weak_prop;
@property (readwrite) __weak id weak_prop1;
@property () NSString* assignProperty;
@property (assign) NSString* readonlyProp;
@end