Small CapturedStmt improvements

Add a CapturedStmt.h similar to Lambda.h to reduce the typing required to get
to the CapturedRegionKind enum. This also allows codegen to access this enum
without including Sema/ScopeInfo.h.

Also removes some duplicated code for capturing 'this' between CapturedStmt and
Lambda.

Differential Revision: http://llvm-reviews.chandlerc.com/D712



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@180710 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h
index 019e678..1e5892f 100644
--- a/include/clang/AST/Stmt.h
+++ b/include/clang/AST/Stmt.h
@@ -20,6 +20,7 @@
 #include "clang/Basic/LLVM.h"
 #include "clang/Basic/SourceLocation.h"
 #include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/PointerIntPair.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/ErrorHandling.h"
 #include <string>
@@ -1903,7 +1904,7 @@
 
   /// \brief Describes the capture of either a variable or 'this'.
   class Capture {
-    VarDecl *Var;
+    llvm::PointerIntPair<VarDecl *, 1, VariableCaptureKind> VarAndKind;
     SourceLocation Loc;
 
   public:
@@ -1916,7 +1917,7 @@
     /// \param Var The variable being captured, or null if capturing this.
     ///
     Capture(SourceLocation Loc, VariableCaptureKind Kind, VarDecl *Var = 0)
-      : Var(Var), Loc(Loc) {
+      : VarAndKind(Var, Kind), Loc(Loc) {
       switch (Kind) {
       case VCK_This:
         assert(Var == 0 && "'this' capture cannot have a variable!");
@@ -1928,29 +1929,24 @@
     }
 
     /// \brief Determine the kind of capture.
-    VariableCaptureKind getCaptureKind() const {
-      if (capturesThis())
-        return VCK_This;
-
-      return VCK_ByRef;
-    }
+    VariableCaptureKind getCaptureKind() const { return VarAndKind.getInt(); }
 
     /// \brief Retrieve the source location at which the variable or 'this' was
     /// first used.
     SourceLocation getLocation() const { return Loc; }
 
     /// \brief Determine whether this capture handles the C++ 'this' pointer.
-    bool capturesThis() const { return Var == 0; }
+    bool capturesThis() const { return getCaptureKind() == VCK_This; }
 
     /// \brief Determine whether this capture handles a variable.
-    bool capturesVariable() const { return Var != 0; }
+    bool capturesVariable() const { return getCaptureKind() != VCK_This; }
 
     /// \brief Retrieve the declaration of the variable being captured.
     ///
     /// This operation is only valid if this capture does not capture 'this'.
     VarDecl *getCapturedVar() const {
       assert(!capturesThis() && "No variable available for 'this' capture");
-      return Var;
+      return VarAndKind.getPointer();
     }
   };
 
diff --git a/include/clang/Basic/CapturedStmt.h b/include/clang/Basic/CapturedStmt.h
new file mode 100644
index 0000000..484bbb1
--- /dev/null
+++ b/include/clang/Basic/CapturedStmt.h
@@ -0,0 +1,23 @@
+//===--- CapturedStmt.h - Types for CapturedStmts ---------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+
+#ifndef LLVM_CLANG_BASIC_CAPTUREDSTMT_H
+#define LLVM_CLANG_BASIC_CAPTUREDSTMT_H
+
+namespace clang {
+
+/// \brief The different kinds of captured statement.
+enum CapturedRegionKind {
+  CR_Default
+};
+
+} // end namespace clang
+
+#endif // LLVM_CLANG_BASIC_CAPTUREDSTMT_H
diff --git a/include/clang/Sema/ScopeInfo.h b/include/clang/Sema/ScopeInfo.h
index 103ce82..c8cc696 100644
--- a/include/clang/Sema/ScopeInfo.h
+++ b/include/clang/Sema/ScopeInfo.h
@@ -16,6 +16,7 @@
 #define LLVM_CLANG_SEMA_SCOPE_INFO_H
 
 #include "clang/AST/Type.h"
+#include "clang/Basic/CapturedStmt.h"
 #include "clang/Basic/PartialDiagnostic.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/SmallVector.h"
@@ -499,11 +500,6 @@
 /// \brief Retains information about a captured region.
 class CapturedRegionScopeInfo: public CapturingScopeInfo {
 public:
-
-  enum CapturedRegionKind {
-    CR_Default
-  };
-
   /// \brief The CapturedDecl for this statement.
   CapturedDecl *TheCapturedDecl;
   /// \brief The captured record type.
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index b1b7df2..70a930a 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -927,7 +927,7 @@
   void PushLambdaScope(CXXRecordDecl *Lambda, CXXMethodDecl *CallOperator);
   void PushCapturedRegionScope(Scope *RegionScope, CapturedDecl *CD,
                                RecordDecl *RD,
-                               sema::CapturedRegionScopeInfo::CapturedRegionKind K);
+                               CapturedRegionKind K);
   void PopFunctionScopeInfo(const sema::AnalysisBasedWarnings::Policy *WP =0,
                             const Decl *D = 0, const BlockExpr *blkExpr = 0);
 
@@ -2782,7 +2782,7 @@
   StmtResult ActOnBreakStmt(SourceLocation BreakLoc, Scope *CurScope);
 
   void ActOnCapturedRegionStart(SourceLocation Loc, Scope *CurScope,
-                                sema::CapturedRegionScopeInfo::CapturedRegionKind Kind);
+                                CapturedRegionKind Kind);
   StmtResult ActOnCapturedRegionEnd(Stmt *S);
   void ActOnCapturedRegionError(bool IsInstantiation = false);
   RecordDecl *CreateCapturedStmtRecordDecl(CapturedDecl *&CD,
diff --git a/lib/Parse/ParsePragma.cpp b/lib/Parse/ParsePragma.cpp
index 96328e2..0ecd11e 100644
--- a/lib/Parse/ParsePragma.cpp
+++ b/lib/Parse/ParsePragma.cpp
@@ -136,8 +136,7 @@
   SourceLocation Loc = Tok.getLocation();
 
   ParseScope CapturedRegionScope(this, Scope::FnScope | Scope::DeclScope);
-  Actions.ActOnCapturedRegionStart(Loc, getCurScope(),
-                                   sema::CapturedRegionScopeInfo::CR_Default);
+  Actions.ActOnCapturedRegionStart(Loc, getCurScope(), CR_Default);
 
   StmtResult R = ParseCompoundStatement();
   CapturedRegionScope.Exit();
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp
index 203b689..38c5854 100644
--- a/lib/Sema/Sema.cpp
+++ b/lib/Sema/Sema.cpp
@@ -1316,7 +1316,7 @@
 }
 
 void Sema::PushCapturedRegionScope(Scope *S, CapturedDecl *CD, RecordDecl *RD,
-                                   CapturedRegionScopeInfo::CapturedRegionKind K) {
+                                   CapturedRegionKind K) {
   CapturingScopeInfo *CSI = new CapturedRegionScopeInfo(getDiagnostics(),
                                                         S, CD, RD, K);
   CSI->ReturnType = Context.VoidTy;
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index 65ad83d..c05d29d 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -728,6 +728,18 @@
   }
 }
 
+static Expr *captureThis(ASTContext &Context, RecordDecl *RD,
+                         QualType ThisTy, SourceLocation Loc) {
+  FieldDecl *Field
+    = FieldDecl::Create(Context, RD, Loc, Loc, 0, ThisTy,
+                        Context.getTrivialTypeSourceInfo(ThisTy, Loc),
+                        0, false, ICIS_NoInit);
+  Field->setImplicit(true);
+  Field->setAccess(AS_private);
+  RD->addDecl(Field);
+  return new (Context) CXXThisExpr(Loc, ThisTy, /*isImplicit*/true);
+}
+
 void Sema::CheckCXXThisCapture(SourceLocation Loc, bool Explicit) {
   // We don't need to capture this in an unevaluated context.
   if (ExprEvalContexts.back().Context == Unevaluated && !Explicit)
@@ -768,29 +780,12 @@
     CapturingScopeInfo *CSI = cast<CapturingScopeInfo>(FunctionScopes[idx]);
     Expr *ThisExpr = 0;
     QualType ThisTy = getCurrentThisType();
-    if (LambdaScopeInfo *LSI = dyn_cast<LambdaScopeInfo>(CSI)) {
+    if (LambdaScopeInfo *LSI = dyn_cast<LambdaScopeInfo>(CSI))
       // For lambda expressions, build a field and an initializing expression.
-      CXXRecordDecl *Lambda = LSI->Lambda;
-      FieldDecl *Field
-        = FieldDecl::Create(Context, Lambda, Loc, Loc, 0, ThisTy,
-                            Context.getTrivialTypeSourceInfo(ThisTy, Loc),
-                            0, false, ICIS_NoInit);
-      Field->setImplicit(true);
-      Field->setAccess(AS_private);
-      Lambda->addDecl(Field);
-      ThisExpr = new (Context) CXXThisExpr(Loc, ThisTy, /*isImplicit=*/true);
-    } else if (CapturedRegionScopeInfo *RSI =
-                   dyn_cast<CapturedRegionScopeInfo>(FunctionScopes[idx])) {
-      RecordDecl *RD = RSI->TheRecordDecl;
-      FieldDecl *Field
-        = FieldDecl::Create(Context, RD, Loc, Loc, 0, ThisTy,
-                            Context.getTrivialTypeSourceInfo(ThisTy, Loc),
-                            0, false, ICIS_NoInit);
-      Field->setImplicit(true);
-      Field->setAccess(AS_private);
-      RD->addDecl(Field);
-      ThisExpr = new (Context) CXXThisExpr(Loc, ThisTy, /*isImplicit*/true);
-    }
+      ThisExpr = captureThis(Context, LSI->Lambda, ThisTy, Loc);
+    else if (CapturedRegionScopeInfo *RSI
+        = dyn_cast<CapturedRegionScopeInfo>(FunctionScopes[idx]))
+      ThisExpr = captureThis(Context, RSI->TheRecordDecl, ThisTy, Loc);
 
     bool isNested = NumClosures > 1;
     CSI->addThisCapture(isNested, Loc, ThisTy, ThisExpr);
diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp
index 7286d16..4fc1818 100644
--- a/lib/Sema/SemaStmt.cpp
+++ b/lib/Sema/SemaStmt.cpp
@@ -2970,7 +2970,7 @@
 }
 
 void Sema::ActOnCapturedRegionStart(SourceLocation Loc, Scope *CurScope,
-                                    CapturedRegionScopeInfo::CapturedRegionKind Kind) {
+                                    CapturedRegionKind Kind) {
   CapturedDecl *CD = 0;
   RecordDecl *RD = CreateCapturedStmtRecordDecl(CD, Loc);