An insomniac stab at making block declarations list the variables they close
on, as well as more reliably limiting invalid references to locals from
nested scopes.
llvm-svn: 124721
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index 7bc9af1..73e9778 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -16,6 +16,7 @@
#include "clang/Sema/Initialization.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/ParsedTemplate.h"
+#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/TemplateDeduction.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/CXXInheritance.h"
@@ -563,14 +564,23 @@
/// is a non-lvalue expression whose value is the address of the object for
/// which the function is called.
- DeclContext *DC = getFunctionLevelDeclContext();
- if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(DC))
- if (MD->isInstance())
- return Owned(new (Context) CXXThisExpr(ThisLoc,
- MD->getThisType(Context),
- /*isImplicit=*/false));
+ // Ignore block scopes (but nothing else).
+ DeclContext *DC = CurContext;
+ while (isa<BlockDecl>(DC)) DC = cast<BlockDecl>(DC)->getDeclContext();
- return ExprError(Diag(ThisLoc, diag::err_invalid_this_use));
+ // If we're not an instance method, error out.
+ CXXMethodDecl *method = dyn_cast<CXXMethodDecl>(DC);
+ if (!method || !method->isInstance())
+ return ExprError(Diag(ThisLoc, diag::err_invalid_this_use));
+
+ // 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)
+ cast<BlockScopeInfo>(FunctionScopes[idx])->CapturesCXXThis = true;
+
+ return Owned(new (Context) CXXThisExpr(ThisLoc, method->getThisType(Context),
+ /*isImplicit=*/false));
}
ExprResult