summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2011-02-03 09:00:02 +0000
committerJohn McCall <rjmccall@apple.com>2011-02-03 09:00:02 +0000
commit5f2d556a92137aac34d5a1ff34a4458831c8e584 (patch)
treeeb7328ef9ebf4d1b1358c05297f4c12ac7def9b1 /clang/lib/Sema
parentf3a8860ee1031a56ba05d9a33840e6a6a9dd3854 (diff)
downloadbcm5719-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.cpp40
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();
OpenPOWER on IntegriCloud