diff options
| author | John McCall <rjmccall@apple.com> | 2011-02-03 09:00:02 +0000 |
|---|---|---|
| committer | John McCall <rjmccall@apple.com> | 2011-02-03 09:00:02 +0000 |
| commit | 5f2d556a92137aac34d5a1ff34a4458831c8e584 (patch) | |
| tree | eb7328ef9ebf4d1b1358c05297f4c12ac7def9b1 /clang/lib/Sema | |
| parent | f3a8860ee1031a56ba05d9a33840e6a6a9dd3854 (diff) | |
| download | bcm5719-llvm-5f2d556a92137aac34d5a1ff34a4458831c8e584.tar.gz bcm5719-llvm-5f2d556a92137aac34d5a1ff34a4458831c8e584.zip | |
Capture a few implicit references to 'self'.
llvm-svn: 124786
Diffstat (limited to 'clang/lib/Sema')
| -rw-r--r-- | clang/lib/Sema/SemaExprObjC.cpp | 40 |
1 files changed, 37 insertions, 3 deletions
diff --git a/clang/lib/Sema/SemaExprObjC.cpp b/clang/lib/Sema/SemaExprObjC.cpp index cc087a1a2d0..20fe6aba884 100644 --- a/clang/lib/Sema/SemaExprObjC.cpp +++ b/clang/lib/Sema/SemaExprObjC.cpp @@ -14,6 +14,7 @@ #include "clang/Sema/SemaInternal.h" #include "clang/Sema/Lookup.h" #include "clang/Sema/Scope.h" +#include "clang/Sema/ScopeInfo.h" #include "clang/Sema/Initialization.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclObjC.h" @@ -23,6 +24,7 @@ #include "clang/Lex/Preprocessor.h" using namespace clang; +using namespace sema; ExprResult Sema::ParseObjCStringLiteral(SourceLocation *AtLocs, Expr **strings, @@ -195,6 +197,37 @@ ExprResult Sema::ParseObjCProtocolExpression(IdentifierInfo *ProtocolId, return new (Context) ObjCProtocolExpr(Ty, PDecl, AtLoc, RParenLoc); } +/// Try to capture an implicit reference to 'self'. +ObjCMethodDecl *Sema::tryCaptureObjCSelf() { + // Ignore block scopes: we can capture through them. + DeclContext *DC = CurContext; + while (true) { + if (isa<BlockDecl>(DC)) DC = cast<BlockDecl>(DC)->getDeclContext(); + else if (isa<EnumDecl>(DC)) DC = cast<EnumDecl>(DC)->getDeclContext(); + else break; + } + + // If we're not in an ObjC method, error out. Note that, unlike the + // C++ case, we don't require an instance method --- class methods + // still have a 'self', and we really do still need to capture it! + ObjCMethodDecl *method = dyn_cast<ObjCMethodDecl>(DC); + if (!method) + return 0; + + ImplicitParamDecl *self = method->getSelfDecl(); + assert(self && "capturing 'self' in non-definition?"); + + // Mark that we're closing on 'this' in all the block scopes, if applicable. + for (unsigned idx = FunctionScopes.size() - 1; + isa<BlockScopeInfo>(FunctionScopes[idx]); + --idx) + if (!cast<BlockScopeInfo>(FunctionScopes[idx])->Captures.insert(self)) + break; + + return method; +} + + bool Sema::CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs, Selector Sel, ObjCMethodDecl *Method, bool isClassMessage, @@ -503,8 +536,8 @@ ActOnClassPropertyRefExpr(IdentifierInfo &receiverName, if (IFace == 0) { // If the "receiver" is 'super' in a method, handle it as an expression-like // property reference. - if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) - if (receiverNamePtr->isStr("super")) { + if (receiverNamePtr->isStr("super")) { + if (ObjCMethodDecl *CurMethod = tryCaptureObjCSelf()) { if (CurMethod->isInstanceMethod()) { QualType T = Context.getObjCInterfaceType(CurMethod->getClassInterface()); @@ -520,6 +553,7 @@ ActOnClassPropertyRefExpr(IdentifierInfo &receiverName, // superclass. IFace = CurMethod->getClassInterface()->getSuperClass(); } + } if (IFace == 0) { Diag(receiverNameLoc, diag::err_expected_ident_or_lparen); @@ -700,7 +734,7 @@ ExprResult Sema::ActOnSuperMessage(Scope *S, SourceLocation RBracLoc, MultiExprArg Args) { // Determine whether we are inside a method or not. - ObjCMethodDecl *Method = getCurMethodDecl(); + ObjCMethodDecl *Method = tryCaptureObjCSelf(); if (!Method) { Diag(SuperLoc, diag::err_invalid_receiver_to_message_super); return ExprError(); |

