Implemented access check for ivars accessed inside

c-style functions declared inside objc @implementations.

llvm-svn: 66087
This commit is contained in:
Fariborz Jahanian 2009-03-04 22:30:12 +00:00
parent 19ce8619da
commit b8d091c4eb
7 changed files with 32 additions and 23 deletions

View File

@ -517,7 +517,8 @@ namespace {
SourceLocation OpLoc,
tok::TokenKind OpKind,
SourceLocation MemberLoc,
IdentifierInfo &Member) {
IdentifierInfo &Member,
DeclTy *ImplDecl) {
llvm::cout << __FUNCTION__ << "\n";
return ExprEmpty();
}

View File

@ -642,7 +642,8 @@ public:
SourceLocation OpLoc,
tok::TokenKind OpKind,
SourceLocation MemberLoc,
IdentifierInfo &Member) {
IdentifierInfo &Member,
DeclTy *ObjCImpDecl) {
return ExprEmpty();
}

View File

@ -852,7 +852,8 @@ Parser::ParsePostfixExpressionSuffix(OwningExprResult LHS) {
if (!LHS.isInvalid()) {
LHS = Actions.ActOnMemberReferenceExpr(CurScope, move(LHS), OpLoc,
OpKind, Tok.getLocation(),
*Tok.getIdentifierInfo());
*Tok.getIdentifierInfo(),
ObjCImpDecl);
}
ConsumeToken();
break;

View File

@ -1082,12 +1082,15 @@ Parser::DeclTy *Parser::ParseObjCAtImplementationDeclaration(
Parser::DeclTy *Parser::ParseObjCAtEndDeclaration(SourceLocation atLoc) {
assert(Tok.isObjCAtKeyword(tok::objc_end) &&
"ParseObjCAtEndDeclaration(): Expected @end");
DeclTy *Result = ObjCImpDecl;
ConsumeToken(); // the "end" identifier
if (ObjCImpDecl)
if (ObjCImpDecl) {
Actions.ActOnAtEnd(atLoc, ObjCImpDecl);
ObjCImpDecl = 0;
}
else
Diag(atLoc, diag::warn_expected_implementation); // missing @implementation
return ObjCImpDecl;
return Result;
}
/// compatibility-alias-decl:

View File

@ -1158,7 +1158,8 @@ public:
SourceLocation OpLoc,
tok::TokenKind OpKind,
SourceLocation MemberLoc,
IdentifierInfo &Member);
IdentifierInfo &Member,
DeclTy *ImplDecl=0);
bool ConvertArgumentsForCall(CallExpr *Call, Expr *Fn,
FunctionDecl *FDecl,
const FunctionProtoType *Proto,

View File

@ -1666,16 +1666,11 @@ static IdentifierInfo *constructSetterName(IdentifierTable &Idents,
return &Idents.get(&SelectorName[0], &SelectorName[SelectorName.size()]);
}
ObjCImplementationDecl *getCurImplementationDecl(DeclContext *DC) {
while (DC && !isa<ObjCImplementationDecl>(DC))
DC = DC->getParent();
return dyn_cast_or_null<ObjCImplementationDecl>(DC);
}
Action::OwningExprResult
Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc,
tok::TokenKind OpKind, SourceLocation MemberLoc,
IdentifierInfo &Member) {
IdentifierInfo &Member,
DeclTy *ObjCImpDecl) {
Expr *BaseExpr = static_cast<Expr *>(Base.release());
assert(BaseExpr && "no record expression");
@ -1803,17 +1798,24 @@ Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc,
ObjCInterfaceDecl *ClassOfMethodDecl = 0;
if (ObjCMethodDecl *MD = getCurMethodDecl())
ClassOfMethodDecl = MD->getClassInterface();
else if (FunctionDecl *FD = getCurFunctionDecl()) {
// FIXME: This isn't working yet. Will discuss with Fariborz.
// FIXME: Should be ObjCImplDecl, so categories can work.
// Need to fiddle with castToDeclContext/castFromDeclContext.
ObjCImplementationDecl *ImpDecl = getCurImplementationDecl(FD);
if (ImpDecl)
ClassOfMethodDecl = ImpDecl->getClassInterface();
else if (ObjCImpDecl && getCurFunctionDecl()) {
// Case of a c-function declared inside an objc implementation.
// FIXME: For a c-style function nested inside an objc implementation
// class, there is no implementation context available, so we pass down
// the context as argument to this routine. Ideally, this context need
// be passed down in the AST node and somehow calculated from the AST
// for a function decl.
Decl *ImplDecl = static_cast<Decl *>(ObjCImpDecl);
if (ObjCImplementationDecl *IMPD =
dyn_cast<ObjCImplementationDecl>(ImplDecl))
ClassOfMethodDecl = IMPD->getClassInterface();
else if (ObjCCategoryImplDecl* CatImplClass =
dyn_cast<ObjCCategoryImplDecl>(ImplDecl))
ClassOfMethodDecl = CatImplClass->getClassInterface();
}
if (IV->getAccessControl() == ObjCIvarDecl::Private) {
if (IV->getAccessControl() == ObjCIvarDecl::Private) {
if (ClassDeclared != IFTy->getDecl() ||
(ClassOfMethodDecl && (ClassOfMethodDecl != ClassDeclared)))
ClassOfMethodDecl != ClassDeclared)
Diag(MemberLoc, diag::error_private_ivar_access) << IV->getDeclName();
}
// @protected

View File

@ -73,7 +73,7 @@ int main (void)
{
MySuperClass *s = 0;
int access;
access = s->private; // FIXME: {{instance variable 'private' is private}}
access = s->private; // expected-error {{instance variable 'private' is private}}
access = s->protected; // expected-error {{instance variable 'protected' is protected}}
return 0;
}