forked from OSchip/llvm-project
When using an unavailable/deprecated interface Foo inside Foo's interface/implementation
don't emit unavailable errors. llvm-svn: 141334
This commit is contained in:
parent
1456cd20b4
commit
9321ad3f97
|
@ -520,11 +520,11 @@ private:
|
|||
explicit ObjCDeclContextSwitch(Parser &p) : P(p),
|
||||
DC(p.getObjCDeclContext()) {
|
||||
if (DC)
|
||||
P.Actions.ActOnObjCContainerFinishDefinition();
|
||||
P.Actions.ActOnObjCTemporaryExitContainerContext();
|
||||
}
|
||||
~ObjCDeclContextSwitch() {
|
||||
if (DC)
|
||||
P.Actions.ActOnObjCContainerStartDefinition(DC);
|
||||
P.Actions.ActOnObjCReenterContainerContext();
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -202,6 +202,10 @@ public:
|
|||
/// CurContext - This is the current declaration context of parsing.
|
||||
DeclContext *CurContext;
|
||||
|
||||
/// \brief Generally null except when we temporarily switch decl contexts,
|
||||
/// like in \see ActOnObjCTemporaryExitContainerContext.
|
||||
DeclContext *OriginalLexicalContext;
|
||||
|
||||
/// VAListTagName - The declaration name corresponding to __va_list_tag.
|
||||
/// This is used as part of a hack to omit that class from ADL results.
|
||||
DeclarationName VAListTagName;
|
||||
|
@ -1224,7 +1228,7 @@ public:
|
|||
/// struct, or union).
|
||||
void ActOnTagStartDefinition(Scope *S, Decl *TagDecl);
|
||||
|
||||
void ActOnObjCContainerStartDefinition(Decl *IDecl);
|
||||
Decl *ActOnObjCContainerStartDefinition(Decl *IDecl);
|
||||
|
||||
/// ActOnStartCXXMemberDeclarations - Invoked when we have parsed a
|
||||
/// C++ record definition's base-specifiers clause and are starting its
|
||||
|
@ -1240,6 +1244,13 @@ public:
|
|||
|
||||
void ActOnObjCContainerFinishDefinition();
|
||||
|
||||
/// \brief Invoked when we must temporarily exit the objective-c container
|
||||
/// scope for parsing/looking-up C constructs.
|
||||
///
|
||||
/// Must be followed by a call to \see ActOnObjCReenterContainerContext
|
||||
void ActOnObjCTemporaryExitContainerContext();
|
||||
void ActOnObjCReenterContainerContext();
|
||||
|
||||
/// ActOnTagDefinitionError - Invoked when there was an unrecoverable
|
||||
/// error parsing the definition of a tag.
|
||||
void ActOnTagDefinitionError(Scope *S, Decl *TagDecl);
|
||||
|
@ -6150,6 +6161,10 @@ public:
|
|||
Scope *getCurScope() const { return CurScope; }
|
||||
|
||||
Decl *getObjCDeclContext() const;
|
||||
|
||||
DeclContext *getCurLexicalContext() const {
|
||||
return OriginalLexicalContext ? OriginalLexicalContext : CurContext;
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief RAII object that enters a new expression evaluation context.
|
||||
|
|
|
@ -336,7 +336,6 @@ void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey,
|
|||
tok::ObjCKeywordKind MethodImplKind = tok::objc_not_keyword;
|
||||
|
||||
SourceRange AtEnd;
|
||||
Actions.ActOnObjCContainerStartDefinition(CDecl);
|
||||
|
||||
while (1) {
|
||||
// If this is a method prototype, parse it.
|
||||
|
@ -1195,6 +1194,7 @@ void Parser::ParseObjCClassInstanceVariables(Decl *interfaceDecl,
|
|||
SmallVector<Decl *, 32> AllIvarDecls;
|
||||
|
||||
ParseScope ClassScope(this, Scope::DeclScope|Scope::ClassScope);
|
||||
ObjCDeclContextSwitch ObjCDC(*this);
|
||||
|
||||
SourceLocation LBraceLoc = ConsumeBrace(); // the "{"
|
||||
|
||||
|
@ -1441,7 +1441,6 @@ Decl *Parser::ParseObjCAtImplementationDeclaration(
|
|||
atLoc, nameId, nameLoc, categoryId,
|
||||
categoryLoc);
|
||||
|
||||
Actions.ActOnObjCContainerStartDefinition(ImplCatType);
|
||||
ObjCImpDecl = ImplCatType;
|
||||
PendingObjCImpDecl.push_back(ObjCImpDecl);
|
||||
return 0;
|
||||
|
@ -1466,7 +1465,6 @@ Decl *Parser::ParseObjCAtImplementationDeclaration(
|
|||
if (Tok.is(tok::l_brace)) // we have ivars
|
||||
ParseObjCClassInstanceVariables(ImplClsType, tok::objc_private, atLoc);
|
||||
|
||||
Actions.ActOnObjCContainerStartDefinition(ImplClsType);
|
||||
ObjCImpDecl = ImplClsType;
|
||||
PendingObjCImpDecl.push_back(ObjCImpDecl);
|
||||
return 0;
|
||||
|
|
|
@ -95,7 +95,8 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
|
|||
LangOpts(pp.getLangOptions()), PP(pp), Context(ctxt), Consumer(consumer),
|
||||
Diags(PP.getDiagnostics()), SourceMgr(PP.getSourceManager()),
|
||||
CollectStats(false), ExternalSource(0), CodeCompleter(CodeCompleter),
|
||||
CurContext(0), PackContext(0), MSStructPragmaOn(false), VisContext(0),
|
||||
CurContext(0), OriginalLexicalContext(0),
|
||||
PackContext(0), MSStructPragmaOn(false), VisContext(0),
|
||||
ExprNeedsCleanups(0), LateTemplateParser(0), OpaqueParser(0),
|
||||
IdResolver(pp.getLangOptions()), CXXTypeInfoDecl(0), MSVCGuidDecl(0),
|
||||
GlobalNewDeleteDeclared(false),
|
||||
|
|
|
@ -8004,13 +8004,14 @@ void Sema::ActOnTagStartDefinition(Scope *S, Decl *TagD) {
|
|||
PushDeclContext(S, Tag);
|
||||
}
|
||||
|
||||
void Sema::ActOnObjCContainerStartDefinition(Decl *IDecl) {
|
||||
Decl *Sema::ActOnObjCContainerStartDefinition(Decl *IDecl) {
|
||||
assert(isa<ObjCContainerDecl>(IDecl) &&
|
||||
"ActOnObjCContainerStartDefinition - Not ObjCContainerDecl");
|
||||
DeclContext *OCD = cast<DeclContext>(IDecl);
|
||||
assert(getContainingDC(OCD) == CurContext &&
|
||||
"The next DeclContext should be lexically contained in the current one.");
|
||||
CurContext = OCD;
|
||||
return IDecl;
|
||||
}
|
||||
|
||||
void Sema::ActOnStartCXXMemberDeclarations(Scope *S, Decl *TagD,
|
||||
|
@ -8069,6 +8070,16 @@ void Sema::ActOnObjCContainerFinishDefinition() {
|
|||
PopDeclContext();
|
||||
}
|
||||
|
||||
void Sema::ActOnObjCTemporaryExitContainerContext() {
|
||||
OriginalLexicalContext = CurContext;
|
||||
ActOnObjCContainerFinishDefinition();
|
||||
}
|
||||
|
||||
void Sema::ActOnObjCReenterContainerContext() {
|
||||
ActOnObjCContainerStartDefinition(cast<Decl>(OriginalLexicalContext));
|
||||
OriginalLexicalContext = 0;
|
||||
}
|
||||
|
||||
void Sema::ActOnTagDefinitionError(Scope *S, Decl *TagD) {
|
||||
AdjustDeclIfTemplate(TagD);
|
||||
TagDecl *Tag = cast<TagDecl>(TagD);
|
||||
|
|
|
@ -4031,7 +4031,7 @@ void Sema::EmitDeprecationWarning(NamedDecl *D, StringRef Message,
|
|||
}
|
||||
|
||||
// Otherwise, don't warn if our current context is deprecated.
|
||||
if (isDeclDeprecated(cast<Decl>(CurContext)))
|
||||
if (isDeclDeprecated(cast<Decl>(getCurLexicalContext())))
|
||||
return;
|
||||
if (!Message.empty())
|
||||
Diag(Loc, diag::warn_deprecated_message) << D->getDeclName()
|
||||
|
|
|
@ -374,7 +374,7 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
|
|||
|
||||
// Return the previous class interface.
|
||||
// FIXME: don't leak the objects passed in!
|
||||
return IDecl;
|
||||
return ActOnObjCContainerStartDefinition(IDecl);
|
||||
} else {
|
||||
IDecl->setLocation(ClassLoc);
|
||||
IDecl->setForwardDecl(false);
|
||||
|
@ -482,7 +482,7 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
|
|||
}
|
||||
|
||||
CheckObjCDeclScope(IDecl);
|
||||
return IDecl;
|
||||
return ActOnObjCContainerStartDefinition(IDecl);
|
||||
}
|
||||
|
||||
/// ActOnCompatiblityAlias - this action is called after complete parsing of
|
||||
|
@ -578,7 +578,7 @@ Sema::ActOnStartProtocolInterface(SourceLocation AtProtoInterfaceLoc,
|
|||
Diag(PDecl->getLocation(), diag::note_previous_definition);
|
||||
// Just return the protocol we already had.
|
||||
// FIXME: don't leak the objects passed in!
|
||||
return PDecl;
|
||||
return ActOnObjCContainerStartDefinition(PDecl);
|
||||
}
|
||||
ObjCList<ObjCProtocolDecl> PList;
|
||||
PList.set((ObjCProtocolDecl *const*)ProtoRefs, NumProtoRefs, Context);
|
||||
|
@ -611,7 +611,7 @@ Sema::ActOnStartProtocolInterface(SourceLocation AtProtoInterfaceLoc,
|
|||
}
|
||||
|
||||
CheckObjCDeclScope(PDecl);
|
||||
return PDecl;
|
||||
return ActOnObjCContainerStartDefinition(PDecl);
|
||||
}
|
||||
|
||||
/// FindProtocolDeclaration - This routine looks up protocols and
|
||||
|
@ -741,7 +741,7 @@ ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc,
|
|||
ClassLoc, CategoryLoc, CategoryName,IDecl);
|
||||
CDecl->setInvalidDecl();
|
||||
Diag(ClassLoc, diag::err_undef_interface) << ClassName;
|
||||
return CDecl;
|
||||
return ActOnObjCContainerStartDefinition(CDecl);
|
||||
}
|
||||
|
||||
if (!CategoryName && IDecl->getImplementation()) {
|
||||
|
@ -783,7 +783,7 @@ ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc,
|
|||
}
|
||||
|
||||
CheckObjCDeclScope(CDecl);
|
||||
return CDecl;
|
||||
return ActOnObjCContainerStartDefinition(CDecl);
|
||||
}
|
||||
|
||||
/// ActOnStartCategoryImplementation - Perform semantic checks on the
|
||||
|
@ -836,7 +836,7 @@ Decl *Sema::ActOnStartCategoryImplementation(
|
|||
}
|
||||
|
||||
CheckObjCDeclScope(CDecl);
|
||||
return CDecl;
|
||||
return ActOnObjCContainerStartDefinition(CDecl);
|
||||
}
|
||||
|
||||
Decl *Sema::ActOnStartClassImplementation(
|
||||
|
@ -930,7 +930,7 @@ Decl *Sema::ActOnStartClassImplementation(
|
|||
ClassLoc, AtClassImplLoc);
|
||||
|
||||
if (CheckObjCDeclScope(IMPDecl))
|
||||
return IMPDecl;
|
||||
return ActOnObjCContainerStartDefinition(IMPDecl);
|
||||
|
||||
// Check that there is no duplicate implementation of this class.
|
||||
if (IDecl->getImplementation()) {
|
||||
|
@ -947,7 +947,7 @@ Decl *Sema::ActOnStartClassImplementation(
|
|||
dyn_cast<NamedDecl>(IDecl),
|
||||
IMPDecl->getLocation(), 1);
|
||||
}
|
||||
return IMPDecl;
|
||||
return ActOnObjCContainerStartDefinition(IMPDecl);
|
||||
}
|
||||
|
||||
void Sema::CheckImplementationIvars(ObjCImplementationDecl *ImpDecl,
|
||||
|
|
|
@ -72,7 +72,8 @@ static AvailabilityResult DiagnoseAvailabilityOfDecl(Sema &S,
|
|||
break;
|
||||
|
||||
case AR_Unavailable:
|
||||
if (cast<Decl>(S.CurContext)->getAvailability() != AR_Unavailable) {
|
||||
if (cast<Decl>(S.getCurLexicalContext())->getAvailability() !=
|
||||
AR_Unavailable) {
|
||||
if (Message.empty()) {
|
||||
if (!UnknownObjCClass)
|
||||
S.Diag(Loc, diag::err_unavailable) << D->getDeclName();
|
||||
|
|
|
@ -85,8 +85,10 @@ int t5() {
|
|||
__attribute ((deprecated))
|
||||
@interface DEPRECATED {
|
||||
@public int ivar;
|
||||
DEPRECATED *ivar2; // no warning.
|
||||
}
|
||||
- (int) instancemethod;
|
||||
- (DEPRECATED *) meth; // no warning.
|
||||
@property int prop;
|
||||
@end
|
||||
|
||||
|
|
|
@ -2,17 +2,25 @@
|
|||
// rdar://9092208
|
||||
|
||||
__attribute__((unavailable("not available")))
|
||||
@interface MyClass { // expected-note 5 {{declaration has been explicitly marked unavailable here}}
|
||||
@interface MyClass { // expected-note 7 {{declaration has been explicitly marked unavailable here}}
|
||||
@public
|
||||
void *_test;
|
||||
MyClass *ivar; // no error.
|
||||
}
|
||||
|
||||
- (id)self;
|
||||
- new;
|
||||
+ (void)addObject:(id)anObject;
|
||||
- (MyClass *)meth; // no error.
|
||||
|
||||
@end
|
||||
|
||||
@interface Foo {
|
||||
MyClass *ivar; // expected-error {{unavailable}}
|
||||
}
|
||||
- (MyClass *)meth; // expected-error {{unavailable}}
|
||||
@end
|
||||
|
||||
int main() {
|
||||
[MyClass new]; // expected-error {{'MyClass' is unavailable: not available}}
|
||||
[MyClass self]; // expected-error {{'MyClass' is unavailable: not available}}
|
||||
|
|
Loading…
Reference in New Issue