Hi doug.gregor, hfinkel, rsmith, fraggamuffin, ejstotzer,

An updated implemnentation of VLA types capturing based on previously committed 
solution for Lambdas.
This version captures the whole VLA type instead of particular variables which 
are part of VLA size expression and allows to use previusly calculated size of 
VLA type in captured regions. Required for OpenMP.

http://reviews.llvm.org/D5099

Files:
  include/clang/AST/Decl.h
  include/clang/AST/Stmt.h
  lib/AST/Decl.cpp
  lib/CodeGen/CGStmt.cpp
  lib/CodeGen/CodeGenFunction.h
  lib/Sema/ScopeInfo.cpp
  lib/Sema/SemaExpr.cpp
  lib/Sema/SemaStmt.cpp
  lib/Serialization/ASTWriterStmt.cpp
  test/CodeGen/captured-statements-nested.c
  test/CodeGen/captured-statements.c
Index: include/clang/AST/Decl.h
===================================================================
--- include/clang/AST/Decl.h
+++ include/clang/AST/Decl.h
@@ -3161,6 +3161,10 @@
   /// function object.
   bool isLambda() const;
 
+  /// \brief Determine whether this record is a record for captured variables in
+  /// CapturedStmt construct.
+  bool isCapturedRecord() const;
+
   /// getDefinition - Returns the RecordDecl that actually defines
   ///  this struct/union/class.  When determining whether or not a
   ///  struct/union/class is completely defined, one should use this
Index: include/clang/AST/Stmt.h
===================================================================
--- include/clang/AST/Stmt.h
+++ include/clang/AST/Stmt.h
@@ -1977,15 +1977,18 @@
 /// @endcode
 class CapturedStmt : public Stmt {
 public:
-  /// \brief The different capture forms: by 'this' or by reference, etc.
+  /// \brief The different capture forms: by 'this', by reference, capture for
+  /// variable-length array type etc.
   enum VariableCaptureKind {
     VCK_This,
-    VCK_ByRef
+    VCK_ByRef,
+    VCK_VLAType
   };
 
-  /// \brief Describes the capture of either a variable or 'this'.
+  /// \brief Describes the capture of either a variable, or 'this', or
+  /// variable-length array type.
   class Capture {
-    llvm::PointerIntPair<VarDecl *, 1, VariableCaptureKind> VarAndKind;
+    llvm::PointerIntPair<VarDecl *, 2, VariableCaptureKind> VarAndKind;
     SourceLocation Loc;
 
   public:
@@ -2007,6 +2010,10 @@
       case VCK_ByRef:
         assert(Var && "capturing by reference must have a variable!");
         break;
+      case VCK_VLAType:
+        assert(!Var &&
+               "Variable-length array type capture cannot have a variable!");
+        break;
       }
     }
 
@@ -2021,13 +2028,20 @@
     bool capturesThis() const { return getCaptureKind() == VCK_This; }
 
     /// \brief Determine whether this capture handles a variable.
-    bool capturesVariable() const { return getCaptureKind() != VCK_This; }
+    bool capturesVariable() const { return getCaptureKind() == VCK_ByRef; }
+
+    /// \brief Determine whether this capture handles a variable-length array
+    /// type.
+    bool capturesVariableArrayType() const {
+      return getCaptureKind() == VCK_VLAType;
+    }
 
     /// \brief Retrieve the declaration of the variable being captured.
     ///
-    /// This operation is only valid if this capture does not capture 'this'.
+    /// This operation is only valid if this capture captures a variable.
     VarDecl *getCapturedVar() const {
-      assert(!capturesThis() && "No variable available for 'this' capture");
+      assert(capturesVariable() &&
+             "No variable available for 'this' or VAT capture");
       return VarAndKind.getPointer();
     }
     friend class ASTStmtReader;
Index: lib/AST/Decl.cpp
===================================================================
--- lib/AST/Decl.cpp
+++ lib/AST/Decl.cpp
@@ -3261,11 +3261,17 @@
   return false;
 }
 
+static bool isVLATypeCapturingAllowed(const RecordDecl *RD) {
+  // Allow variable-length array capturing in Lambdas and CapturedStmts.
+  return RD->isLambda() || RD->isCapturedRecord();
+}
+
 bool FieldDecl::isBitField() const {
   if (getInClassInitStyle() == ICIS_NoInit &&
       InitializerOrBitWidth.getPointer()) {
     assert(getDeclContext() && "No parent context for FieldDecl");
-    return !getDeclContext()->isRecord() || !getParent()->isLambda();
+    return !getDeclContext()->isRecord() ||
+           !isVLATypeCapturingAllowed(getParent());
   }
   return false;
 }
@@ -3315,12 +3321,14 @@
 }
 
 bool FieldDecl::hasCapturedVLAType() const {
-  return getDeclContext()->isRecord() && getParent()->isLambda() &&
+  return getDeclContext()->isRecord() &&
+         isVLATypeCapturingAllowed(getParent()) &&
          InitializerOrBitWidth.getPointer();
 }
 
 void FieldDecl::setCapturedVLAType(const VariableArrayType *VLAType) {
-  assert(getParent()->isLambda() && "capturing type in non-lambda.");
+  assert(isVLATypeCapturingAllowed(getParent()) &&
+         "capturing type in non-lambda.");
   assert(!InitializerOrBitWidth.getPointer() && !hasInClassInitializer() &&
          "bit width, initializer or captured type already set");
   InitializerOrBitWidth.setPointer(const_cast<VariableArrayType *>(VLAType));
@@ -3552,6 +3560,12 @@
   return false;
 }
 
+bool RecordDecl::isCapturedRecord() const {
+  return getTagKind() == TTK_Struct && getLocStart() == getLocation() &&
+         getIdentifier() == nullptr && isImplicit() &&
+         !isAnonymousStructOrUnion();
+}
+
 RecordDecl::field_iterator RecordDecl::field_begin() const {
   if (hasExternalLexicalStorage() && !LoadedFieldsFromExternalStorage)
     LoadFieldsFromExternalStorage();
Index: lib/CodeGen/CGStmt.cpp
===================================================================
--- lib/CodeGen/CGStmt.cpp
+++ lib/CodeGen/CGStmt.cpp
@@ -2068,46 +2068,35 @@
   }
 }
 
-static LValue InitCapturedStruct(CodeGenFunction &CGF, const CapturedStmt &S) {
+LValue CodeGenFunction::InitCapturedStruct(const CapturedStmt &S) {
   const RecordDecl *RD = S.getCapturedRecordDecl();
-  QualType RecordTy = CGF.getContext().getRecordType(RD);
+  QualType RecordTy = getContext().getRecordType(RD);
 
   // Initialize the captured struct.
-  LValue SlotLV = CGF.MakeNaturalAlignAddrLValue(
-                    CGF.CreateMemTemp(RecordTy, "agg.captured"), RecordTy);
+  LValue SlotLV = MakeNaturalAlignAddrLValue(
+      CreateMemTemp(RecordTy, "agg.captured"), RecordTy);
 
   RecordDecl::field_iterator CurField = RD->field_begin();
   for (CapturedStmt::capture_init_iterator I = S.capture_init_begin(),
                                            E = S.capture_init_end();
        I != E; ++I, ++CurField) {
-    LValue LV = CGF.EmitLValueForFieldInitialization(SlotLV, *CurField);
-    CGF.EmitInitializerForField(*CurField, LV, *I, None);
+    LValue LV = EmitLValueForFieldInitialization(SlotLV, *CurField);
+    if (CurField->hasCapturedVLAType()) {
+      auto VAT = CurField->getCapturedVLAType();
+      EmitStoreThroughLValue(RValue::get(VLASizeMap[VAT->getSizeExpr()]), LV);
+    } else {
+      EmitInitializerForField(*CurField, LV, *I, None);
+    }
   }
 
   return SlotLV;
 }
 
-static void InitVLACaptures(CodeGenFunction &CGF, const CapturedStmt &S) {
-  for (auto &C : S.captures()) {
-    if (C.capturesVariable()) {
-      QualType QTy;
-      auto VD = C.getCapturedVar();
-      if (const ParmVarDecl *PVD = dyn_cast<ParmVarDecl>(VD))
-        QTy = PVD->getOriginalType();
-      else
-        QTy = VD->getType();
-      if (QTy->isVariablyModifiedType()) {
-        CGF.EmitVariablyModifiedType(QTy);
-      }
-    }
-  }
-}
-
 /// Generate an outlined function for the body of a CapturedStmt, store any
 /// captured variables into the captured struct, and call the outlined function.
 llvm::Function *
 CodeGenFunction::EmitCapturedStmt(const CapturedStmt &S, CapturedRegionKind K) {
-  LValue CapStruct = InitCapturedStruct(*this, S);
+  LValue CapStruct = InitCapturedStruct(S);
 
   // Emit the CapturedDecl
   CodeGenFunction CGF(CGM, true);
@@ -2123,7 +2112,7 @@
 
 llvm::Value *
 CodeGenFunction::GenerateCapturedStmtArgument(const CapturedStmt &S) {
-  LValue CapStruct = InitCapturedStruct(*this, S);
+  LValue CapStruct = InitCapturedStruct(S);
   return CapStruct.getAddress();
 }
 
@@ -2164,14 +2153,21 @@
   CapturedStmtInfo->setContextValue(Builder.CreateLoad(DeclPtr));
 
   // Initialize variable-length arrays.
-  InitVLACaptures(*this, S);
+  LValue Base = MakeNaturalAlignAddrLValue(CapturedStmtInfo->getContextValue(),
+                                           Ctx.getTagDeclType(RD));
+  for (auto *FD : RD->fields()) {
+    if (FD->hasCapturedVLAType()) {
+      auto *ExprArg = EmitLoadOfLValue(EmitLValueForField(Base, FD),
+                                       SourceLocation()).getScalarVal();
+      auto VAT = FD->getCapturedVLAType();
+      VLASizeMap[VAT->getSizeExpr()] = ExprArg;
+    }
+  }
 
   // If 'this' is captured, load it into CXXThisValue.
   if (CapturedStmtInfo->isCXXThisExprCaptured()) {
     FieldDecl *FD = CapturedStmtInfo->getThisFieldDecl();
-    LValue LV = MakeNaturalAlignAddrLValue(CapturedStmtInfo->getContextValue(),
-                                           Ctx.getTagDeclType(RD));
-    LValue ThisLValue = EmitLValueForField(LV, FD);
+    LValue ThisLValue = EmitLValueForField(Base, FD);
     CXXThisValue = EmitLoadOfLValue(ThisLValue, Loc).getScalarVal();
   }
 
Index: lib/CodeGen/CodeGenFunction.h
===================================================================
--- lib/CodeGen/CodeGenFunction.h
+++ lib/CodeGen/CodeGenFunction.h
@@ -193,7 +193,7 @@
            I != E; ++I, ++Field) {
         if (I->capturesThis())
           CXXThisFieldDecl = *Field;
-        else
+        else if (I->capturesVariable())
           CaptureFields[I->getCapturedVar()] = *Field;
       }
     }
@@ -1924,6 +1924,7 @@
   void EmitCXXForRangeStmt(const CXXForRangeStmt &S,
                            ArrayRef<const Attr *> Attrs = None);
 
+  LValue InitCapturedStruct(const CapturedStmt &S);
   llvm::Function *EmitCapturedStmt(const CapturedStmt &S, CapturedRegionKind K);
   llvm::Function *GenerateCapturedStmtFunction(const CapturedStmt &S);
   llvm::Value *GenerateCapturedStmtArgument(const CapturedStmt &S);
Index: lib/Sema/ScopeInfo.cpp
===================================================================
--- lib/Sema/ScopeInfo.cpp
+++ lib/Sema/ScopeInfo.cpp
@@ -95,8 +95,14 @@
 }
 
 bool CapturingScopeInfo::isVLATypeCaptured(const VariableArrayType *VAT) const {
+  RecordDecl *RD = nullptr;
   if (auto *LSI = dyn_cast<LambdaScopeInfo>(this))
-    for (auto *FD : LSI->Lambda->fields()) {
+    RD = LSI->Lambda;
+  else if (auto CRSI = dyn_cast<CapturedRegionScopeInfo>(this))
+    RD = CRSI->TheRecordDecl;
+
+  if (RD)
+    for (auto *FD : RD->fields()) {
       if (FD->hasCapturedVLAType() && FD->getCapturedVLAType() == VAT)
         return true;
     }
Index: lib/Sema/SemaExpr.cpp
===================================================================
--- lib/Sema/SemaExpr.cpp
+++ lib/Sema/SemaExpr.cpp
@@ -12229,29 +12229,29 @@
           // Unknown size indication requires no size computation.
           // Otherwise, evaluate and record it.
           if (auto Size = VAT->getSizeExpr()) {
-            if (auto LSI = dyn_cast<LambdaScopeInfo>(CSI)) {
-              if (!LSI->isVLATypeCaptured(VAT)) {
+            if (!CSI->isVLATypeCaptured(VAT)) {
+              RecordDecl *CapRecord = nullptr;
+              if (auto LSI = dyn_cast<LambdaScopeInfo>(CSI)) {
+                CapRecord = LSI->Lambda;
+              } else if (auto CRSI = dyn_cast<CapturedRegionScopeInfo>(CSI)) {
+                CapRecord = CRSI->TheRecordDecl;
+              }
+              if (CapRecord) {
                 auto ExprLoc = Size->getExprLoc();
                 auto SizeType = Context.getSizeType();
-                auto Lambda = LSI->Lambda;
-
                 // Build the non-static data member.
                 auto Field = FieldDecl::Create(
-                    Context, Lambda, ExprLoc, ExprLoc,
+                    Context, CapRecord, ExprLoc, ExprLoc,
                     /*Id*/ nullptr, SizeType, /*TInfo*/ nullptr,
                     /*BW*/ nullptr, /*Mutable*/ false,
                     /*InitStyle*/ ICIS_NoInit);
                 Field->setImplicit(true);
                 Field->setAccess(AS_private);
                 Field->setCapturedVLAType(VAT);
-                Lambda->addDecl(Field);
+                CapRecord->addDecl(Field);
 
-                LSI->addVLATypeCapture(ExprLoc, SizeType);
+                CSI->addVLATypeCapture(ExprLoc, SizeType);
               }
-            } else {
-              // Immediately mark all referenced vars for CapturedStatements,
-              // they all are captured by reference.
-              MarkDeclarationsReferencedInExpr(Size);
             }
           }
           QTy = VAT->getElementType();
Index: lib/Sema/SemaStmt.cpp
===================================================================
--- lib/Sema/SemaStmt.cpp
+++ lib/Sema/SemaStmt.cpp
@@ -3352,6 +3352,11 @@
                                                CapturedStmt::VCK_This));
       CaptureInits.push_back(Cap->getInitExpr());
       continue;
+    } else if (Cap->isVLATypeCapture()) {
+      Captures.push_back(
+          CapturedStmt::Capture(Cap->getLocation(), CapturedStmt::VCK_VLAType));
+      CaptureInits.push_back(nullptr);
+      continue;
     }
 
     assert(Cap->isReferenceCapture() &&
Index: lib/Serialization/ASTWriterStmt.cpp
===================================================================
--- lib/Serialization/ASTWriterStmt.cpp
+++ lib/Serialization/ASTWriterStmt.cpp
@@ -307,7 +307,7 @@
 
   // Captures
   for (const auto &I : S->captures()) {
-    if (I.capturesThis())
+    if (I.capturesThis() || I.capturesVariableArrayType())
       Writer.AddDeclRef(nullptr, Record);
     else
       Writer.AddDeclRef(I.getCapturedVar(), Record);
Index: test/CodeGen/captured-statements-nested.c
===================================================================
--- test/CodeGen/captured-statements-nested.c
+++ test/CodeGen/captured-statements-nested.c
@@ -11,9 +11,9 @@
 void test_nest_captured_stmt(int param, int size, int param_arr[size]) {
   int w;
   int arr[param][size];
-  // CHECK1: %struct.anon{{.*}} = type { i32*, i32*, i{{.+}}*, i32**, i32* }
-  // CHECK1: %struct.anon{{.*}} = type { i32*, i32*, i32**, i32*, i{{.+}}*, i32**, i32* }
-  // CHECK1: [[T:%struct.anon.*]] = type { i32*, i32*, %struct.A*, i32**, i32*, i{{.+}}*, i32**, i32* }
+  // CHECK1: %struct.anon{{.*}} = type { [[INT:i.+]]*, [[INT]]*, [[SIZE_TYPE:i.+]], [[INT]]**, [[INT]]*, [[SIZE_TYPE]], [[SIZE_TYPE]], [[INT]]* }
+  // CHECK1: %struct.anon{{.*}} = type { [[INT]]*, [[INT]]*, [[INT]]**, [[INT]]*, [[SIZE_TYPE]], [[INT]]**, [[INT]]*, [[SIZE_TYPE]], [[SIZE_TYPE]], [[INT]]* }
+  // CHECK1: [[T:%struct.anon.*]] = type { [[INT]]*, [[INT]]*, %struct.A*, [[INT]]**, [[INT]]*, [[SIZE_TYPE]], [[INT]]**, [[INT]]*, [[SIZE_TYPE]], [[SIZE_TYPE]], [[INT]]* }
   #pragma clang __debug captured
   {
     int x;
@@ -31,39 +31,45 @@
         arr[10][z.a] = 12;
 
         // CHECK1: define internal void @__captured_stmt{{.*}}([[T]]
+        // CHECK1: [[PARAM_ARR_SIZE_REF:%.+]] = getelementptr inbounds [[T]]* {{.+}}, i{{[0-9]+}} 0, i{{[0-9]+}} 5
+        // CHECK1: [[PARAM_ARR_SIZE:%.+]] = load [[SIZE_TYPE]]* [[PARAM_ARR_SIZE_REF]]
+        // CHECK1: [[ARR_SIZE1_REF:%.+]] = getelementptr inbounds [[T]]* {{.+}}, i{{[0-9]+}} 0, i{{[0-9]+}} 8
+        // CHECK1: [[ARR_SIZE1:%.+]] = load [[SIZE_TYPE]]* [[ARR_SIZE1_REF]]
+        // CHECK1: [[ARR_SIZE2_REF:%.+]] = getelementptr inbounds [[T]]* {{.+}}, i{{[0-9]+}} 0, i{{[0-9]+}} 9
+        // CHECK1: [[ARR_SIZE2:%.+]] = load [[SIZE_TYPE]]* [[ARR_SIZE2_REF]]
         //
-        // CHECK1: getelementptr inbounds [[T]]* {{.*}}, i32 0, i32 2
+        // CHECK1: getelementptr inbounds [[T]]* {{.*}}, i{{[0-9]+}} 0, i{{[0-9]+}} 2
         // CHECK1-NEXT: load %struct.A**
         // CHECK1-NEXT: getelementptr inbounds %struct.A*
         // CHECK1-NEXT: store i{{.+}} 1
         //
-        // CHECK1: getelementptr inbounds [[T]]* {{.*}}, i32 0, i32 1
-        // CHECK1-NEXT: load i32**
-        // CHECK1-NEXT: store i32 1
-        //
-        // CHECK1: getelementptr inbounds [[T]]* {{.*}}, i32 0, i32 0
-        // CHECK1-NEXT: load i32**
-        // CHECK1-NEXT: store i32 1
-        //
-        // CHECK1: getelementptr inbounds [[T]]* {{.*}}, i32 0, i32 4
-        // CHECK1-NEXT: load i32**
-        // CHECK1-NEXT: load i32*
-        // CHECK1-NEXT: getelementptr inbounds [[T]]* {{.*}}, i32 0, i32 3
-        // CHECK1-NEXT: load i32***
-        // CHECK1-NEXT: load i32**
-        // CHECK1-NEXT: store i32
+        // CHECK1: getelementptr inbounds [[T]]* {{.*}}, i{{[0-9]+}} 0, i{{[0-9]+}} 1
+        // CHECK1-NEXT: load i{{[0-9]+}}**
+        // CHECK1-NEXT: store i{{[0-9]+}} 1
+        //
+        // CHECK1: getelementptr inbounds [[T]]* {{.*}}, i{{[0-9]+}} 0, i{{[0-9]+}} 0
+        // CHECK1-NEXT: load i{{[0-9]+}}**
+        // CHECK1-NEXT: store i{{[0-9]+}} 1
+        //
+        // CHECK1: getelementptr inbounds [[T]]* {{.*}}, i{{[0-9]+}} 0, i{{[0-9]+}} 4
+        // CHECK1-NEXT: load i{{[0-9]+}}**
+        // CHECK1-NEXT: load i{{[0-9]+}}*
+        // CHECK1-NEXT: getelementptr inbounds [[T]]* {{.*}}, i{{[0-9]+}} 0, i{{[0-9]+}} 3
+        // CHECK1-NEXT: load i{{[0-9]+}}***
+        // CHECK1-NEXT: load i{{[0-9]+}}**
+        // CHECK1-NEXT: store i{{[0-9]+}}
         //
-        // CHECK1: getelementptr inbounds [[T]]* {{.*}}, i32 0, i32 2
+        // CHECK1: getelementptr inbounds [[T]]* {{.*}}, i{{[0-9]+}} 0, i{{[0-9]+}} 2
         // CHECK1-NEXT: load %struct.A**
         // CHECK1-NEXT: getelementptr inbounds %struct.A*
         // CHECK1-NEXT: store float
         //
-        // CHECK1: getelementptr inbounds [[T]]* {{.*}}, i32 0, i32 2
+        // CHECK1: getelementptr inbounds [[T]]* {{.*}}, i{{[0-9]+}} 0, i{{[0-9]+}} 2
         // CHECK1-NEXT: load %struct.A**
         // CHECK1-NEXT: getelementptr inbounds %struct.A*
         // CHECK1-NEXT: store i8 99
         //
-        // CHECK1: [[SIZE_ADDR_REF:%.*]] = getelementptr inbounds [[T]]* {{.*}}, i{{.+}} 0, i{{.+}} 5
+        // CHECK1: [[SIZE_ADDR_REF:%.*]] = getelementptr inbounds [[T]]* {{.*}}, i{{.+}} 0, i{{.+}} 7
         // CHECK1-DAG: [[SIZE_ADDR:%.*]] = load i{{.+}}** [[SIZE_ADDR_REF]]
         // CHECK1-DAG: [[SIZE:%.*]] = load i{{.+}}* [[SIZE_ADDR]]
         // CHECK1-DAG: [[PARAM_ARR_IDX:%.*]] = sub nsw i{{.+}} [[SIZE]], 1
@@ -77,7 +83,7 @@
         // CHECK1-DAG: [[Z_ADDR:%.*]] = load %struct.A** [[Z_ADDR_REF]]
         // CHECK1-DAG: [[Z_A_ADDR:%.*]] = getelementptr inbounds %struct.A* [[Z_ADDR]], i{{.+}} 0, i{{.+}} 0
         // CHECK1-DAG: [[ARR_IDX_2:%.*]] = load i{{.+}}* [[Z_A_ADDR]]
-        // CHECK1-DAG: [[ARR_ADDR_REF:%.*]] = getelementptr inbounds [[T]]* {{.*}}, i{{.+}} 0, i{{.+}} 7
+        // CHECK1-DAG: [[ARR_ADDR_REF:%.*]] = getelementptr inbounds [[T]]* {{.*}}, i{{.+}} 0, i{{.+}} 10
         // CHECK1-DAG: [[ARR_ADDR:%.*]] = load i{{.+}}** [[ARR_ADDR_REF]]
         // CHECK1-DAG: [[ARR_IDX_1:%.*]] = mul {{.*}} 10
         // CHECK1-DAG: [[ARR_10_ADDR:%.*]] = getelementptr inbounds i{{.+}}* [[ARR_ADDR]], i{{.*}} [[ARR_IDX_1]]
@@ -102,15 +108,15 @@
 
   // CHECK2: define internal void @{{.*}}test_nest_block_block_invoke
   //
-  // CHECK2: [[Z:%[0-9a-z_]*]] = alloca i32
+  // CHECK2: [[Z:%[0-9a-z_]*]] = alloca i{{[0-9]+}}
   // CHECK2: alloca %struct.anon{{.*}}
   //
-  // CHECK2: store i32
-  // CHECK2: store i32* [[Z]]
+  // CHECK2: store i{{[0-9]+}}
+  // CHECK2: store i{{[0-9]+}}* [[Z]]
   //
   // CHECK2: getelementptr inbounds %struct.anon
   // CHECK2-NEXT: getelementptr inbounds
-  // CHECK2-NEXT: store i32*
+  // CHECK2-NEXT: store i{{[0-9]+}}*
   //
   // CHECK2: call void @__captured_stmt
 
@@ -128,22 +134,22 @@
   }
 
   // CHECK2: alloca %struct.__block_byref_b
-  // CHECK2-NEXT: [[C:%[0-9a-z_]*]] = alloca i32
+  // CHECK2-NEXT: [[C:%[0-9a-z_]*]] = alloca i{{[0-9]+}}
   // CHECK2-NEXT: alloca %struct.__block_byref_d
   //
   // CHECK2: bitcast %struct.__block_byref_b*
   // CHECK2-NEXT: store i8*
   //
-  // CHECK2: [[CapA:%[0-9a-z_.]*]] = getelementptr inbounds {{.*}}, i32 0, i32 7
+  // CHECK2: [[CapA:%[0-9a-z_.]*]] = getelementptr inbounds {{.*}}, i{{[0-9]+}} 0, i{{[0-9]+}} 7
   //
-  // CHECK2: getelementptr inbounds %struct.anon{{.*}}, i32 0, i32 0
-  // CHECK2: load i32**
-  // CHECK2: load i32*
-  // CHECK2: store i32 {{.*}}, i32* [[CapA]]
-  //
-  // CHECK2: [[CapC:%[0-9a-z_.]*]] = getelementptr inbounds {{.*}}, i32 0, i32 8
-  // CHECK2-NEXT: [[Val:%[0-9a-z_]*]] = load i32* [[C]]
-  // CHECK2-NEXT: store i32 [[Val]], i32* [[CapC]]
+  // CHECK2: getelementptr inbounds %struct.anon{{.*}}, i{{[0-9]+}} 0, i{{[0-9]+}} 0
+  // CHECK2: load i{{[0-9]+}}**
+  // CHECK2: load i{{[0-9]+}}*
+  // CHECK2: store i{{[0-9]+}} {{.*}}, i{{[0-9]+}}* [[CapA]]
+  //
+  // CHECK2: [[CapC:%[0-9a-z_.]*]] = getelementptr inbounds {{.*}}, i{{[0-9]+}} 0, i{{[0-9]+}} 8
+  // CHECK2-NEXT: [[Val:%[0-9a-z_]*]] = load i{{[0-9]+}}* [[C]]
+  // CHECK2-NEXT: store i{{[0-9]+}} [[Val]], i{{[0-9]+}}* [[CapC]]
   //
   // CHECK2: bitcast %struct.__block_byref_d*
   // CHECK2-NEXT: store i8*
Index: test/CodeGen/captured-statements.c
===================================================================
--- test/CodeGen/captured-statements.c
+++ test/CodeGen/captured-statements.c
@@ -4,6 +4,8 @@
 // RUN: FileCheck %s -input-file=%t -check-prefix=CHECK-2
 // RUN: FileCheck %s -input-file=%t -check-prefix=CHECK-3
 
+typedef __INTPTR_TYPE__ intptr_t;
+
 int foo();
 int global;
 
@@ -61,15 +63,16 @@
 }
 
 // Capture VLA array
-void test4(int size, int vla_arr[size]) {
+void test4(intptr_t size, intptr_t vla_arr[size]) {
   #pragma clang __debug captured
   {
     vla_arr[0] = 1;
   }
-  // CHECK-3: test4([[INT:i.+]] {{.*}}[[SIZE:%.+]], [[INT]]*
-  // CHECK-3: store [[INT]] {{.*}}[[SIZE]], [[INT]]* [[SIZE_ADDR:%.+]],
+  // CHECK-3: test4([[INTPTR_T:i.+]] {{.*}}[[SIZE_ARG:%.+]], [[INTPTR_T]]*
+  // CHECK-3: store [[INTPTR_T]] {{.*}}[[SIZE_ARG]], [[INTPTR_T]]* [[SIZE_ADDR:%.+]],
+  // CHECK-3: [[SIZE:%.+]] = load [[INTPTR_T]]* [[SIZE_ADDR]],
   // CHECK-3: [[REF:%.+]] = getelementptr inbounds
-  // CHECK-3: store [[INT]]* [[SIZE_ADDR]], [[INT]]** [[REF]]
+  // CHECK-3: store [[INTPTR_T]] [[SIZE]], [[INTPTR_T]]* [[REF]]
   // CHECK-3: call void @__captured_stmt
 }
 
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to