mirror of https://github.com/microsoft/clang.git
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:
parent
c568e2f801
commit
dad633b0a0
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
Loading…
Reference in New Issue