forked from OSchip/llvm-project
objective-c: Normally, a property cannot be both 'readonly' and having a
"write" attribute (copy/retain/etc.). But, property declaration in primary class and protcols are tentative as they may be overridden into a 'readwrite' property in class extensions. Postpone diagnosing such warnings until the class implementation is seen. // rdar://11656982 llvm-svn: 158869
This commit is contained in:
parent
2d2dec96e0
commit
876cc65a3f
|
@ -6006,7 +6006,8 @@ public:
|
|||
/// be modified to be consistent with \arg PropertyTy.
|
||||
void CheckObjCPropertyAttributes(Decl *PropertyPtrTy,
|
||||
SourceLocation Loc,
|
||||
unsigned &Attributes);
|
||||
unsigned &Attributes,
|
||||
bool propertyInPrimaryClass);
|
||||
|
||||
/// Process the specified property declaration and create decls for the
|
||||
/// setters and getters as needed.
|
||||
|
|
|
@ -135,7 +135,6 @@ Decl *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc,
|
|||
|
||||
// Proceed with constructing the ObjCPropertDecls.
|
||||
ObjCContainerDecl *ClassDecl = cast<ObjCContainerDecl>(CurContext);
|
||||
|
||||
if (ObjCCategoryDecl *CDecl = dyn_cast<ObjCCategoryDecl>(ClassDecl))
|
||||
if (CDecl->IsClassExtension()) {
|
||||
Decl *Res = HandlePropertyInClassExtension(S, AtLoc, LParenLoc,
|
||||
|
@ -146,7 +145,7 @@ Decl *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc,
|
|||
isOverridingProperty, TSI,
|
||||
MethodImplKind);
|
||||
if (Res) {
|
||||
CheckObjCPropertyAttributes(Res, AtLoc, Attributes);
|
||||
CheckObjCPropertyAttributes(Res, AtLoc, Attributes, false);
|
||||
if (getLangOpts().ObjCAutoRefCount)
|
||||
checkARCPropertyDecl(*this, cast<ObjCPropertyDecl>(Res));
|
||||
}
|
||||
|
@ -163,7 +162,9 @@ Decl *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc,
|
|||
Res->setLexicalDeclContext(lexicalDC);
|
||||
|
||||
// Validate the attributes on the @property.
|
||||
CheckObjCPropertyAttributes(Res, AtLoc, Attributes);
|
||||
CheckObjCPropertyAttributes(Res, AtLoc, Attributes,
|
||||
(isa<ObjCInterfaceDecl>(ClassDecl) ||
|
||||
isa<ObjCProtocolDecl>(ClassDecl)));
|
||||
|
||||
if (getLangOpts().ObjCAutoRefCount)
|
||||
checkARCPropertyDecl(*this, Res);
|
||||
|
@ -601,6 +602,67 @@ static void setImpliedPropertyAttributeForReadOnlyProperty(
|
|||
return;
|
||||
}
|
||||
|
||||
/// DiagnoseClassAndClassExtPropertyMismatch - diagnose inconsistant property
|
||||
/// attribute declared in primary class and attributes overridden in any of its
|
||||
/// class extensions.
|
||||
static void
|
||||
DiagnoseClassAndClassExtPropertyMismatch(Sema &S, ObjCInterfaceDecl *ClassDecl,
|
||||
ObjCPropertyDecl *property) {
|
||||
unsigned Attributes = property->getPropertyAttributesAsWritten();
|
||||
bool warn = (Attributes & ObjCDeclSpec::DQ_PR_readonly);
|
||||
for (const ObjCCategoryDecl *CDecl = ClassDecl->getFirstClassExtension();
|
||||
CDecl; CDecl = CDecl->getNextClassExtension()) {
|
||||
warn = false;
|
||||
ObjCPropertyDecl *ClassExtProperty = 0;
|
||||
for (ObjCContainerDecl::prop_iterator P = CDecl->prop_begin(),
|
||||
E = CDecl->prop_end(); P != E; ++P) {
|
||||
if ((*P)->getIdentifier() == property->getIdentifier()) {
|
||||
ClassExtProperty = *P;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ClassExtProperty) {
|
||||
unsigned classExtPropertyAttr =
|
||||
ClassExtProperty->getPropertyAttributesAsWritten();
|
||||
// We are issuing the warning that we postponed because class extensions
|
||||
// can override readonly->readwrite and 'setter' attributes originally
|
||||
// placed on class's property declaration now make sense in the overridden
|
||||
// property.
|
||||
if (Attributes & ObjCDeclSpec::DQ_PR_readonly) {
|
||||
if (!classExtPropertyAttr ||
|
||||
(classExtPropertyAttr & ObjCDeclSpec::DQ_PR_readwrite))
|
||||
continue;
|
||||
warn = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (warn) {
|
||||
unsigned setterAttrs = (ObjCDeclSpec::DQ_PR_assign |
|
||||
ObjCDeclSpec::DQ_PR_unsafe_unretained |
|
||||
ObjCDeclSpec::DQ_PR_copy |
|
||||
ObjCDeclSpec::DQ_PR_retain |
|
||||
ObjCDeclSpec::DQ_PR_strong);
|
||||
if (Attributes & setterAttrs) {
|
||||
const char * which =
|
||||
(Attributes & ObjCDeclSpec::DQ_PR_assign) ?
|
||||
"assign" :
|
||||
(Attributes & ObjCDeclSpec::DQ_PR_unsafe_unretained) ?
|
||||
"unsafe_unretained" :
|
||||
(Attributes & ObjCDeclSpec::DQ_PR_copy) ?
|
||||
"copy" :
|
||||
(Attributes & ObjCDeclSpec::DQ_PR_retain) ?
|
||||
"retain" : "strong";
|
||||
|
||||
S.Diag(property->getLocation(),
|
||||
diag::warn_objc_property_attr_mutually_exclusive)
|
||||
<< "readonly" << which;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// ActOnPropertyImplDecl - This routine performs semantic checks and
|
||||
/// builds the AST node for a property implementation declaration; declared
|
||||
/// as \@synthesize or \@dynamic.
|
||||
|
@ -681,6 +743,8 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
|
|||
FixItHint::CreateReplacement(ReadonlySourceRange, "readwrite");
|
||||
}
|
||||
}
|
||||
|
||||
DiagnoseClassAndClassExtPropertyMismatch(*this, IDecl, property);
|
||||
|
||||
} else if ((CatImplClass = dyn_cast<ObjCCategoryImplDecl>(ClassImpDecl))) {
|
||||
if (Synthesize) {
|
||||
|
@ -1887,7 +1951,8 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property,
|
|||
|
||||
void Sema::CheckObjCPropertyAttributes(Decl *PDecl,
|
||||
SourceLocation Loc,
|
||||
unsigned &Attributes) {
|
||||
unsigned &Attributes,
|
||||
bool propertyInPrimaryClass) {
|
||||
// FIXME: Improve the reported location.
|
||||
if (!PDecl || PDecl->isInvalidDecl())
|
||||
return;
|
||||
|
@ -1910,9 +1975,18 @@ void Sema::CheckObjCPropertyAttributes(Decl *PDecl,
|
|||
return;
|
||||
}
|
||||
|
||||
if (propertyInPrimaryClass) {
|
||||
// we postpone most property diagnosis until class's implementation
|
||||
// because, its readonly attribute may be overridden in its class
|
||||
// extensions making other attributes, which make no sense, to make sense.
|
||||
if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
|
||||
(Attributes & ObjCDeclSpec::DQ_PR_readwrite))
|
||||
Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
|
||||
<< "readonly" << "readwrite";
|
||||
}
|
||||
// readonly and readwrite/assign/retain/copy conflict.
|
||||
if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
|
||||
(Attributes & (ObjCDeclSpec::DQ_PR_readwrite |
|
||||
else if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
|
||||
(Attributes & (ObjCDeclSpec::DQ_PR_readwrite |
|
||||
ObjCDeclSpec::DQ_PR_assign |
|
||||
ObjCDeclSpec::DQ_PR_unsafe_unretained |
|
||||
ObjCDeclSpec::DQ_PR_copy |
|
||||
|
|
|
@ -29,4 +29,39 @@
|
|||
@end
|
||||
|
||||
|
||||
// rdar://11656982
|
||||
@interface I0 <P0> @end
|
||||
@implementation I0
|
||||
@synthesize X;
|
||||
@end
|
||||
|
||||
@interface I1 <P1> @end
|
||||
@implementation I1
|
||||
@synthesize X;
|
||||
@end
|
||||
|
||||
@interface I2 <P2> @end
|
||||
@implementation I2
|
||||
@synthesize X;
|
||||
@end
|
||||
|
||||
@interface I3 <P3> @end
|
||||
@implementation I3
|
||||
@synthesize X;
|
||||
@end
|
||||
|
||||
@interface I4 <P4> @end
|
||||
@implementation I4
|
||||
@synthesize X;
|
||||
@end
|
||||
|
||||
@interface I5 <P5> @end
|
||||
@implementation I5
|
||||
@synthesize X;
|
||||
@end
|
||||
|
||||
@interface I6 <P6> @end
|
||||
@implementation I6
|
||||
@synthesize X;
|
||||
@end
|
||||
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
// RUN: %clang_cc1 -fsyntax-only -Weverything -verify %s
|
||||
// rdar://11656982
|
||||
/** Normally, a property cannot be both 'readonly' and having a "write" attribute
|
||||
(copy/retain/etc.). But, property declaration in primary class and protcols
|
||||
are tentative as they may be overridden into a 'readwrite' property in class
|
||||
extensions. Postpone diagnosing such warnings until the class implementation
|
||||
is seen.
|
||||
*/
|
||||
|
||||
@interface Super {
|
||||
}
|
||||
@end
|
||||
|
||||
@class NSString;
|
||||
|
||||
@interface MyClass : Super
|
||||
@property(nonatomic, copy, readonly) NSString *prop;
|
||||
@end
|
||||
|
||||
@interface MyClass ()
|
||||
@property(nonatomic, copy, readwrite) NSString *prop;
|
||||
@end
|
||||
|
||||
@implementation MyClass
|
||||
@synthesize prop;
|
||||
@end
|
||||
|
||||
|
||||
@protocol P
|
||||
@property(nonatomic, copy, readonly) NSString *prop;
|
||||
@end
|
||||
|
||||
@interface YourClass : Super <P>
|
||||
@end
|
||||
|
||||
@interface YourClass ()
|
||||
@property(nonatomic, copy, readwrite) NSString *prop;
|
||||
@end
|
||||
|
||||
@implementation YourClass
|
||||
@synthesize prop;
|
||||
@end
|
||||
|
Loading…
Reference in New Issue