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));
 }