aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaExprCXX.cpp
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2011-02-03 08:15:49 +0000
committerJohn McCall <rjmccall@apple.com>2011-02-03 08:15:49 +0000
commit5808ce43f8d7e71f5acacc9ca320268c4f37565a (patch)
tree50a9b47a2ac607cfe51b3498125d8d4b07667e17 /lib/Sema/SemaExprCXX.cpp
parent553304523bcce281aa3b1afe0f84ae34a90a3c86 (diff)
More capturing of 'this': implicit member expressions. Getting that
right for anonymous struct/union members led to me discovering some seemingly broken code in that area of Sema, which I fixed, partly by changing the representation of member pointer constants so that IndirectFieldDecls aren't expanded. This led to assorted cleanups with member pointers in CodeGen, and while I was doing that I saw some random other things to clean up. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@124785 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaExprCXX.cpp')
-rw-r--r--lib/Sema/SemaExprCXX.cpp34
1 files changed, 24 insertions, 10 deletions
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index 73e9778a74..81031a54ee 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -559,19 +559,22 @@ bool Sema::CheckCXXThrowOperand(SourceLocation ThrowLoc, Expr *&E) {
return false;
}
-ExprResult Sema::ActOnCXXThis(SourceLocation ThisLoc) {
- /// C++ 9.3.2: In the body of a non-static member function, the keyword this
- /// is a non-lvalue expression whose value is the address of the object for
- /// which the function is called.
-
- // Ignore block scopes (but nothing else).
+CXXMethodDecl *Sema::tryCaptureCXXThis() {
+ // Ignore block scopes: we can capture through them.
+ // Ignore nested enum scopes: we'll diagnose non-constant expressions
+ // where they're invalid, and other uses are legitimate.
+ // Don't ignore nested class scopes: you can't use 'this' in a local class.
DeclContext *DC = CurContext;
- while (isa<BlockDecl>(DC)) DC = cast<BlockDecl>(DC)->getDeclContext();
+ 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 an instance method, error out.
+ // If we're not in an instance method, error out.
CXXMethodDecl *method = dyn_cast<CXXMethodDecl>(DC);
if (!method || !method->isInstance())
- return ExprError(Diag(ThisLoc, diag::err_invalid_this_use));
+ return 0;
// Mark that we're closing on 'this' in all the block scopes, if applicable.
for (unsigned idx = FunctionScopes.size() - 1;
@@ -579,7 +582,18 @@ ExprResult Sema::ActOnCXXThis(SourceLocation ThisLoc) {
--idx)
cast<BlockScopeInfo>(FunctionScopes[idx])->CapturesCXXThis = true;
- return Owned(new (Context) CXXThisExpr(ThisLoc, method->getThisType(Context),
+ return method;
+}
+
+ExprResult Sema::ActOnCXXThis(SourceLocation loc) {
+ /// C++ 9.3.2: In the body of a non-static member function, the keyword this
+ /// is a non-lvalue expression whose value is the address of the object for
+ /// which the function is called.
+
+ CXXMethodDecl *method = tryCaptureCXXThis();
+ if (!method) return Diag(loc, diag::err_invalid_this_use);
+
+ return Owned(new (Context) CXXThisExpr(loc, method->getThisType(Context),
/*isImplicit=*/false));
}