forked from OSchip/llvm-project
[Sema] Check availability of ObjC super class and protocols of a container
in the context of the container itself. Otherwise we will emit 'unavailable' errors when referencing an unavailable super class even though the subclass is also marked 'unavailable'. rdar://20598702 llvm-svn: 235276
This commit is contained in:
parent
8902e530bc
commit
4ecdd2cff3
|
@ -1240,6 +1240,7 @@ private:
|
|||
bool ParseObjCProtocolReferences(SmallVectorImpl<Decl *> &P,
|
||||
SmallVectorImpl<SourceLocation> &PLocs,
|
||||
bool WarnOnDeclarations,
|
||||
bool ForObjCContainer,
|
||||
SourceLocation &LAngleLoc,
|
||||
SourceLocation &EndProtoLoc);
|
||||
bool ParseObjCProtocolQualifiers(DeclSpec &DS);
|
||||
|
|
|
@ -6952,7 +6952,7 @@ public:
|
|||
unsigned NumElts,
|
||||
AttributeList *attrList);
|
||||
|
||||
void FindProtocolDeclaration(bool WarnOnDeclarations,
|
||||
void FindProtocolDeclaration(bool WarnOnDeclarations, bool ForObjCContainer,
|
||||
const IdentifierLocPair *ProtocolId,
|
||||
unsigned NumProtocols,
|
||||
SmallVectorImpl<Decl *> &Protocols);
|
||||
|
|
|
@ -240,7 +240,7 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc,
|
|||
SmallVector<Decl *, 8> ProtocolRefs;
|
||||
SmallVector<SourceLocation, 8> ProtocolLocs;
|
||||
if (Tok.is(tok::less) &&
|
||||
ParseObjCProtocolReferences(ProtocolRefs, ProtocolLocs, true,
|
||||
ParseObjCProtocolReferences(ProtocolRefs, ProtocolLocs, true, true,
|
||||
LAngleLoc, EndProtoLoc))
|
||||
return nullptr;
|
||||
|
||||
|
@ -286,7 +286,7 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc,
|
|||
SmallVector<SourceLocation, 8> ProtocolLocs;
|
||||
SourceLocation LAngleLoc, EndProtoLoc;
|
||||
if (Tok.is(tok::less) &&
|
||||
ParseObjCProtocolReferences(ProtocolRefs, ProtocolLocs, true,
|
||||
ParseObjCProtocolReferences(ProtocolRefs, ProtocolLocs, true, true,
|
||||
LAngleLoc, EndProtoLoc))
|
||||
return nullptr;
|
||||
|
||||
|
@ -1151,7 +1151,7 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc,
|
|||
bool Parser::
|
||||
ParseObjCProtocolReferences(SmallVectorImpl<Decl *> &Protocols,
|
||||
SmallVectorImpl<SourceLocation> &ProtocolLocs,
|
||||
bool WarnOnDeclarations,
|
||||
bool WarnOnDeclarations, bool ForObjCContainer,
|
||||
SourceLocation &LAngleLoc, SourceLocation &EndLoc) {
|
||||
assert(Tok.is(tok::less) && "expected <");
|
||||
|
||||
|
@ -1186,7 +1186,7 @@ ParseObjCProtocolReferences(SmallVectorImpl<Decl *> &Protocols,
|
|||
return true;
|
||||
|
||||
// Convert the list of protocols identifiers into a list of protocol decls.
|
||||
Actions.FindProtocolDeclaration(WarnOnDeclarations,
|
||||
Actions.FindProtocolDeclaration(WarnOnDeclarations, ForObjCContainer,
|
||||
&ProtocolIdents[0], ProtocolIdents.size(),
|
||||
Protocols);
|
||||
return false;
|
||||
|
@ -1201,6 +1201,7 @@ bool Parser::ParseObjCProtocolQualifiers(DeclSpec &DS) {
|
|||
SmallVector<Decl *, 8> ProtocolDecl;
|
||||
SmallVector<SourceLocation, 8> ProtocolLocs;
|
||||
bool Result = ParseObjCProtocolReferences(ProtocolDecl, ProtocolLocs, false,
|
||||
false,
|
||||
LAngleLoc, EndProtoLoc);
|
||||
DS.setProtocolQualifiers(ProtocolDecl.data(), ProtocolDecl.size(),
|
||||
ProtocolLocs.data(), LAngleLoc);
|
||||
|
@ -1416,7 +1417,7 @@ Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc,
|
|||
SmallVector<Decl *, 8> ProtocolRefs;
|
||||
SmallVector<SourceLocation, 8> ProtocolLocs;
|
||||
if (Tok.is(tok::less) &&
|
||||
ParseObjCProtocolReferences(ProtocolRefs, ProtocolLocs, false,
|
||||
ParseObjCProtocolReferences(ProtocolRefs, ProtocolLocs, false, true,
|
||||
LAngleLoc, EndProtoLoc))
|
||||
return DeclGroupPtrTy();
|
||||
|
||||
|
|
|
@ -448,6 +448,19 @@ class ObjCInterfaceValidatorCCC : public CorrectionCandidateCallback {
|
|||
|
||||
}
|
||||
|
||||
static void diagnoseUseOfProtocols(Sema &TheSema,
|
||||
ObjCContainerDecl *CD,
|
||||
ObjCProtocolDecl *const *ProtoRefs,
|
||||
unsigned NumProtoRefs,
|
||||
const SourceLocation *ProtoLocs) {
|
||||
assert(ProtoRefs);
|
||||
// Diagnose availability in the context of the ObjC container.
|
||||
Sema::ContextRAII SavedContext(TheSema, CD);
|
||||
for (unsigned i = 0; i < NumProtoRefs; ++i) {
|
||||
(void)TheSema.DiagnoseUseOfDecl(ProtoRefs[i], ProtoLocs[i]);
|
||||
}
|
||||
}
|
||||
|
||||
Decl *Sema::
|
||||
ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
|
||||
IdentifierInfo *ClassName, SourceLocation ClassLoc,
|
||||
|
@ -535,6 +548,8 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
|
|||
ObjCInterfaceDecl *SuperClassDecl =
|
||||
dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl);
|
||||
|
||||
// Diagnose availability in the context of the @interface.
|
||||
ContextRAII SavedContext(*this, IDecl);
|
||||
// Diagnose classes that inherit from deprecated classes.
|
||||
if (SuperClassDecl)
|
||||
(void)DiagnoseUseOfDecl(SuperClassDecl, SuperLoc);
|
||||
|
@ -591,6 +606,8 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
|
|||
|
||||
// Check then save referenced protocols.
|
||||
if (NumProtoRefs) {
|
||||
diagnoseUseOfProtocols(*this, IDecl, (ObjCProtocolDecl*const*)ProtoRefs,
|
||||
NumProtoRefs, ProtoLocs);
|
||||
IDecl->setProtocolList((ObjCProtocolDecl*const*)ProtoRefs, NumProtoRefs,
|
||||
ProtoLocs, Context);
|
||||
IDecl->setEndOfDefinitionLoc(EndProtoLoc);
|
||||
|
@ -751,6 +768,8 @@ Sema::ActOnStartProtocolInterface(SourceLocation AtProtoInterfaceLoc,
|
|||
|
||||
if (!err && NumProtoRefs ) {
|
||||
/// Check then save referenced protocols.
|
||||
diagnoseUseOfProtocols(*this, PDecl, (ObjCProtocolDecl*const*)ProtoRefs,
|
||||
NumProtoRefs, ProtoLocs);
|
||||
PDecl->setProtocolList((ObjCProtocolDecl*const*)ProtoRefs, NumProtoRefs,
|
||||
ProtoLocs, Context);
|
||||
}
|
||||
|
@ -778,7 +797,7 @@ static bool NestedProtocolHasNoDefinition(ObjCProtocolDecl *PDecl,
|
|||
/// issues an error if they are not declared. It returns list of
|
||||
/// protocol declarations in its 'Protocols' argument.
|
||||
void
|
||||
Sema::FindProtocolDeclaration(bool WarnOnDeclarations,
|
||||
Sema::FindProtocolDeclaration(bool WarnOnDeclarations, bool ForObjCContainer,
|
||||
const IdentifierLocPair *ProtocolId,
|
||||
unsigned NumProtocols,
|
||||
SmallVectorImpl<Decl *> &Protocols) {
|
||||
|
@ -804,8 +823,12 @@ Sema::FindProtocolDeclaration(bool WarnOnDeclarations,
|
|||
// If this is a forward protocol declaration, get its definition.
|
||||
if (!PDecl->isThisDeclarationADefinition() && PDecl->getDefinition())
|
||||
PDecl = PDecl->getDefinition();
|
||||
|
||||
(void)DiagnoseUseOfDecl(PDecl, ProtocolId[i].second);
|
||||
|
||||
// For an objc container, delay protocol reference checking until after we
|
||||
// can set the objc decl as the availability context, otherwise check now.
|
||||
if (!ForObjCContainer) {
|
||||
(void)DiagnoseUseOfDecl(PDecl, ProtocolId[i].second);
|
||||
}
|
||||
|
||||
// If this is a forward declaration and we are supposed to warn in this
|
||||
// case, do it.
|
||||
|
@ -934,7 +957,9 @@ ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc,
|
|||
CurContext->addDecl(CDecl);
|
||||
|
||||
if (NumProtoRefs) {
|
||||
CDecl->setProtocolList((ObjCProtocolDecl*const*)ProtoRefs, NumProtoRefs,
|
||||
diagnoseUseOfProtocols(*this, CDecl, (ObjCProtocolDecl*const*)ProtoRefs,
|
||||
NumProtoRefs, ProtoLocs);
|
||||
CDecl->setProtocolList((ObjCProtocolDecl*const*)ProtoRefs, NumProtoRefs,
|
||||
ProtoLocs, Context);
|
||||
// Protocols in the class extension belong to the class.
|
||||
if (CDecl->IsClassExtension())
|
||||
|
|
|
@ -67,3 +67,34 @@ Foo *g_foo = 0; // expected-error {{'Foo' is unavailable}}
|
|||
Foo * f_func() { // expected-error {{'Foo' is unavailable}}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define UNAVAILABLE __attribute__((unavailable("not available")))
|
||||
|
||||
UNAVAILABLE
|
||||
@interface Base // expected-note {{unavailable here}}
|
||||
@end
|
||||
|
||||
UNAVAILABLE
|
||||
@protocol SomeProto // expected-note 4 {{unavailable here}}
|
||||
@end
|
||||
|
||||
@interface Sub : Base<SomeProto> // expected-error 2 {{unavailable}}
|
||||
@end
|
||||
@interface IP<SomeProto> // expected-error {{unavailable}}
|
||||
@end
|
||||
@protocol SubProt<SomeProto> // expected-error {{unavailable}}
|
||||
@end
|
||||
@interface Sub(cat)<SomeProto> // expected-error {{unavailable}}
|
||||
@end
|
||||
|
||||
UNAVAILABLE
|
||||
@interface UnavailSub : Base<SomeProto> // no error
|
||||
@end
|
||||
UNAVAILABLE
|
||||
@interface UnavailIP<SomeProto> // no error
|
||||
@end
|
||||
UNAVAILABLE
|
||||
@protocol UnavailProt<SomeProto> // no error
|
||||
@end
|
||||
@interface UnavailSub(cat)<SomeProto> // no error
|
||||
@end
|
||||
|
|
Loading…
Reference in New Issue