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
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index 73e9778..81031a5 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -559,19 +559,22 @@
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 @@
--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));
}