r193223 - Remove the circular reference to LambdaExpr in CXXRecordDecl.

Faisal Vali faisalv at yahoo.com
Tue Oct 22 19:59:28 PDT 2013


Author: faisalv
Date: Tue Oct 22 21:59:27 2013
New Revision: 193223

URL: http://llvm.org/viewvc/llvm-project?rev=193223&view=rev
Log:
Remove the circular reference to LambdaExpr in CXXRecordDecl.

Both Doug and Richard had asked me to remove the circular reference in CXXRecordDecl to LambdaExpr by factoring out and storing the needed information from LambdaExpr directly into CXXRecordDecl.

No change in functionality. 

In addition, I have added an IsGenericLambda flag - this makes life a little easier when we implement capturing, and are Sema-analyzing the body of a lambda (and the calloperator hasn't been wired to the closure class yet). Any inner lambdas can have potential captures that could require walking up the scope chain and checking if any generic lambdas are capture-ready. This 'bit' makes some of that checking easier. 

This patch was approved by Doug with minor modifications (comments were cleaned up, and all data members were converted from bool/enum to unsigned, as requested): 
http://llvm-reviews.chandlerc.com/D1856

Thanks!

Added:
    cfe/trunk/test/PCH/cxx1y-lambdas.mm
Modified:
    cfe/trunk/include/clang/AST/DeclCXX.h
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/AST/DeclCXX.cpp
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaLambda.cpp
    cfe/trunk/lib/Sema/TreeTransform.h
    cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
    cfe/trunk/lib/Serialization/ASTWriter.cpp

Modified: cfe/trunk/include/clang/AST/DeclCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=193223&r1=193222&r2=193223&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclCXX.h (original)
+++ cfe/trunk/include/clang/AST/DeclCXX.h Tue Oct 22 21:59:27 2013
@@ -514,10 +514,12 @@ class CXXRecordDecl : public RecordDecl
   struct LambdaDefinitionData : public DefinitionData {
     typedef LambdaExpr::Capture Capture;
     
-    LambdaDefinitionData(CXXRecordDecl *D, TypeSourceInfo *Info, bool Dependent) 
-      : DefinitionData(D), Dependent(Dependent), NumCaptures(0), 
-        NumExplicitCaptures(0), ManglingNumber(0), ContextDecl(0), 
-        Captures(0), MethodTyInfo(Info), TheLambdaExpr(0) 
+       LambdaDefinitionData(CXXRecordDecl *D, TypeSourceInfo *Info, 
+                         bool Dependent, bool IsGeneric, 
+                         LambdaCaptureDefault CaptureDefault) 
+      : DefinitionData(D), Dependent(Dependent), IsGenericLambda(IsGeneric), 
+        CaptureDefault(CaptureDefault), NumCaptures(0), NumExplicitCaptures(0), 
+        ManglingNumber(0), ContextDecl(0), Captures(0), MethodTyInfo(Info)
     {
       IsLambda = true;
     }
@@ -532,11 +534,17 @@ class CXXRecordDecl : public RecordDecl
     /// artifact of having to parse the default arguments before. 
     unsigned Dependent : 1;
     
-    /// \brief The number of captures in this lambda.
-    unsigned NumCaptures : 16;
+    /// \brief Whether this lambda is a generic lambda.
+    unsigned IsGenericLambda : 1;
+
+    /// \brief The Default Capture.
+    unsigned CaptureDefault : 2;
+
+    /// \brief The number of captures in this lambda is limited 2^NumCaptures.
+    unsigned NumCaptures : 15;
 
     /// \brief The number of explicit captures in this lambda.
-    unsigned NumExplicitCaptures : 15;
+    unsigned NumExplicitCaptures : 13;
 
     /// \brief The number used to indicate this lambda expression for name 
     /// mangling in the Itanium C++ ABI.
@@ -554,9 +562,6 @@ class CXXRecordDecl : public RecordDecl
 
     /// \brief The type of the call method.
     TypeSourceInfo *MethodTyInfo;
-
-    /// \brief The AST node of the lambda expression.
-    LambdaExpr *TheLambdaExpr;
        
   };
 
@@ -669,7 +674,8 @@ public:
                                bool DelayTypeCreation = false);
   static CXXRecordDecl *CreateLambda(const ASTContext &C, DeclContext *DC,
                                      TypeSourceInfo *Info, SourceLocation Loc,
-                                     bool DependentLambda);
+                                     bool DependentLambda, bool IsGeneric, 
+                                     LambdaCaptureDefault CaptureDefault);
   static CXXRecordDecl *CreateDeserialized(const ASTContext &C, unsigned ID);
 
   bool isDynamicClass() const {
@@ -1013,17 +1019,11 @@ public:
   /// lambda.
   TemplateParameterList *getGenericLambdaTemplateParameterList() const;
 
-  /// \brief Assign the member call operator of the lambda. 
-  void setLambdaExpr(LambdaExpr *E) {
-    getLambdaData().TheLambdaExpr = E;
+  LambdaCaptureDefault getLambdaCaptureDefault() const {
+    assert(isLambda());
+    return static_cast<LambdaCaptureDefault>(getLambdaData().CaptureDefault);
   }
 
-  /// \brief Retrieve the parent lambda expression.
-  LambdaExpr *getLambdaExpr() const {
-    return isLambda() ? getLambdaData().TheLambdaExpr : 0;
-  }
-
-
   /// \brief For a closure type, retrieve the mapping from captured
   /// variables and \c this to the non-static data members that store the
   /// values or references of the captures.

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=193223&r1=193222&r2=193223&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Tue Oct 22 21:59:27 2013
@@ -4453,7 +4453,8 @@ public:
   /// \brief Create a new lambda closure type.
   CXXRecordDecl *createLambdaClosureType(SourceRange IntroducerRange,
                                          TypeSourceInfo *Info,
-                                         bool KnownDependent);
+                                         bool KnownDependent, 
+                                         LambdaCaptureDefault CaptureDefault);
 
   /// \brief Start the definition of a lambda expression.
   CXXMethodDecl *startLambdaDefinition(CXXRecordDecl *Class,

Modified: cfe/trunk/lib/AST/DeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=193223&r1=193222&r2=193223&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclCXX.cpp (original)
+++ cfe/trunk/lib/AST/DeclCXX.cpp Tue Oct 22 21:59:27 2013
@@ -108,11 +108,15 @@ CXXRecordDecl *CXXRecordDecl::Create(con
 
 CXXRecordDecl *CXXRecordDecl::CreateLambda(const ASTContext &C, DeclContext *DC,
                                            TypeSourceInfo *Info, SourceLocation Loc,
-                                           bool Dependent) {
+                                           bool Dependent, bool IsGeneric, 
+                                           LambdaCaptureDefault CaptureDefault) {
   CXXRecordDecl* R = new (C) CXXRecordDecl(CXXRecord, TTK_Class, DC, Loc, Loc,
                                            0, 0);
   R->IsBeingDefined = true;
-  R->DefinitionData = new (C) struct LambdaDefinitionData(R, Info, Dependent);
+  R->DefinitionData = new (C) struct LambdaDefinitionData(R, Info, 
+                                                          Dependent, 
+                                                          IsGeneric, 
+                                                          CaptureDefault);
   R->MayHaveOutOfDateDef = false;
   R->setImplicit(true);
   C.getTypeDeclType(R, /*PrevDecl=*/0);
@@ -942,10 +946,10 @@ bool CXXRecordDecl::isCLike() const {
 
   return isPOD() && data().HasOnlyCMembers;
 }
-
+ 
 bool CXXRecordDecl::isGenericLambda() const { 
-  return isLambda() && 
-      getLambdaCallOperator()->getDescribedFunctionTemplate(); 
+  if (!isLambda()) return false;
+  return getLambdaData().IsGenericLambda;
 }
 
 CXXMethodDecl* CXXRecordDecl::getLambdaCallOperator() const {

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=193223&r1=193222&r2=193223&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Tue Oct 22 21:59:27 2013
@@ -9401,6 +9401,29 @@ Sema::CheckForFunctionRedefinition(Funct
   Diag(Definition->getLocation(), diag::note_previous_definition);
   FD->setInvalidDecl();
 }
+static void RebuildLambdaScopeInfo(CXXMethodDecl *CallOperator, 
+                                   Sema &S) {
+  CXXRecordDecl *const LambdaClass = CallOperator->getParent();
+  S.PushLambdaScope();
+  LambdaScopeInfo *LSI = S.getCurLambda();
+  LSI->CallOperator = CallOperator;
+  LSI->Lambda = LambdaClass;
+  LSI->ReturnType = CallOperator->getResultType();
+  const LambdaCaptureDefault LCD = LambdaClass->getLambdaCaptureDefault();
+
+  if (LCD == LCD_None)
+    LSI->ImpCaptureStyle = CapturingScopeInfo::ImpCap_None;
+  else if (LCD == LCD_ByCopy)
+    LSI->ImpCaptureStyle = CapturingScopeInfo::ImpCap_LambdaByval;
+  else if (LCD == LCD_ByRef)
+    LSI->ImpCaptureStyle = CapturingScopeInfo::ImpCap_LambdaByref;
+  DeclarationNameInfo DNI = CallOperator->getNameInfo();
+    
+  LSI->IntroducerRange = DNI.getCXXOperatorNameRange(); 
+  LSI->Mutable = !CallOperator->isConst();
+
+  // FIXME: Add the captures to the LSI.
+}
 
 Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) {
   // Clear the last template instantiation error context.
@@ -9416,31 +9439,18 @@ Decl *Sema::ActOnStartOfFunctionDef(Scop
     FD = cast<FunctionDecl>(D);
   // If we are instantiating a generic lambda call operator, push
   // a LambdaScopeInfo onto the function stack.  But use the information
-  // that's already been calculated (ActOnLambdaExpr) when analyzing the
-  // template version, to prime the current LambdaScopeInfo. 
+  // that's already been calculated (ActOnLambdaExpr) to prime the current 
+  // LambdaScopeInfo.  
+  // When the template operator is being specialized, the LambdaScopeInfo,
+  // has to be properly restored so that tryCaptureVariable doesn't try
+  // and capture any new variables. In addition when calculating potential
+  // captures during transformation of nested lambdas, it is necessary to 
+  // have the LSI properly restored. 
   if (isGenericLambdaCallOperatorSpecialization(FD)) {
-    CXXMethodDecl *CallOperator = cast<CXXMethodDecl>(D);
-    CXXRecordDecl *LambdaClass = CallOperator->getParent();
-    LambdaExpr    *LE = LambdaClass->getLambdaExpr();
-    assert(LE && 
-     "No LambdaExpr of closure class when instantiating a generic lambda!");
     assert(ActiveTemplateInstantiations.size() &&
       "There should be an active template instantiation on the stack " 
       "when instantiating a generic lambda!");
-    PushLambdaScope();
-    LambdaScopeInfo *LSI = getCurLambda();
-    LSI->CallOperator = CallOperator;
-    LSI->Lambda = LambdaClass;
-    LSI->ReturnType = CallOperator->getResultType();
-
-    if (LE->getCaptureDefault() == LCD_None)
-      LSI->ImpCaptureStyle = CapturingScopeInfo::ImpCap_None;
-    else if (LE->getCaptureDefault() == LCD_ByCopy)
-      LSI->ImpCaptureStyle = CapturingScopeInfo::ImpCap_LambdaByval;
-    else if (LE->getCaptureDefault() == LCD_ByRef)
-      LSI->ImpCaptureStyle = CapturingScopeInfo::ImpCap_LambdaByref;
-    
-    LSI->IntroducerRange = LE->getIntroducerRange();
+    RebuildLambdaScopeInfo(cast<CXXMethodDecl>(D), *this);
   }
   else
     // Enter a new function scope
@@ -9804,7 +9814,6 @@ Decl *Sema::ActOnFinishFunctionBody(Decl
     PopDeclContext();
 
   PopFunctionScopeInfo(ActivePolicy, dcl);
-  
   // If any errors have occurred, clear out any temporaries that may have
   // been leftover. This ensures that these temporaries won't be picked up for
   // deletion in some later function.

Modified: cfe/trunk/lib/Sema/SemaLambda.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLambda.cpp?rev=193223&r1=193222&r2=193223&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaLambda.cpp (original)
+++ cfe/trunk/lib/Sema/SemaLambda.cpp Tue Oct 22 21:59:27 2013
@@ -24,17 +24,43 @@
 using namespace clang;
 using namespace sema;
 
+
+static inline TemplateParameterList *
+getGenericLambdaTemplateParameterList(LambdaScopeInfo *LSI, Sema &SemaRef) {
+  if (LSI->GLTemplateParameterList)
+    return LSI->GLTemplateParameterList;
+
+  if (LSI->AutoTemplateParams.size()) {
+    SourceRange IntroRange = LSI->IntroducerRange;
+    SourceLocation LAngleLoc = IntroRange.getBegin();
+    SourceLocation RAngleLoc = IntroRange.getEnd();
+    LSI->GLTemplateParameterList = TemplateParameterList::Create(
+                                   SemaRef.Context, 
+                                   /*Template kw loc*/SourceLocation(), 
+                                   LAngleLoc,
+                                   (NamedDecl**)LSI->AutoTemplateParams.data(),
+                                   LSI->AutoTemplateParams.size(), RAngleLoc);  
+  }
+  return LSI->GLTemplateParameterList;
+}
+
+
+
 CXXRecordDecl *Sema::createLambdaClosureType(SourceRange IntroducerRange,
                                              TypeSourceInfo *Info,
-                                             bool KnownDependent) {
+                                             bool KnownDependent, 
+                                             LambdaCaptureDefault CaptureDefault) {
   DeclContext *DC = CurContext;
   while (!(DC->isFunctionOrMethod() || DC->isRecord() || DC->isFileContext()))
     DC = DC->getParent();
-  
+  bool IsGenericLambda = getGenericLambdaTemplateParameterList(getCurLambda(),
+                                                               *this);  
   // Start constructing the lambda class.
   CXXRecordDecl *Class = CXXRecordDecl::CreateLambda(Context, DC, Info,
                                                      IntroducerRange.getBegin(),
-                                                     KnownDependent);
+                                                     KnownDependent, 
+                                                     IsGenericLambda, 
+                                                     CaptureDefault);
   DC->addDecl(Class);
   
   return Class;
@@ -131,25 +157,6 @@ Sema::ExpressionEvaluationContextRecord:
   return *MangleNumbering;
 }
 
-static inline TemplateParameterList *
-getGenericLambdaTemplateParameterList(LambdaScopeInfo *LSI, Sema &SemaRef) {
-  if (LSI->GLTemplateParameterList)
-    return LSI->GLTemplateParameterList;
-  else if (LSI->AutoTemplateParams.size()) {
-    SourceRange IntroRange = LSI->IntroducerRange;
-    SourceLocation LAngleLoc = IntroRange.getBegin();
-    SourceLocation RAngleLoc = IntroRange.getEnd();
-    LSI->GLTemplateParameterList = 
-          TemplateParameterList::Create(SemaRef.Context, 
-            /* Template kw loc */ SourceLocation(), 
-            LAngleLoc,
-            (NamedDecl**)LSI->AutoTemplateParams.data(), 
-            LSI->AutoTemplateParams.size(), RAngleLoc);  
-  }
-  return LSI->GLTemplateParameterList;
-}
-
-
 CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class,
                                            SourceRange IntroducerRange,
                                            TypeSourceInfo *MethodTypeInfo,
@@ -243,7 +250,8 @@ void Sema::buildLambdaScope(LambdaScopeI
                                         bool ExplicitResultType,
                                         bool Mutable) {
   LSI->CallOperator = CallOperator;
-  LSI->Lambda = CallOperator->getParent();
+  CXXRecordDecl *LambdaClass = CallOperator->getParent();
+  LSI->Lambda = LambdaClass;
   if (CaptureDefault == LCD_ByCopy)
     LSI->ImpCaptureStyle = LambdaScopeInfo::ImpCap_LambdaByval;
   else if (CaptureDefault == LCD_ByRef)
@@ -628,7 +636,7 @@ void Sema::ActOnStartOfLambdaDefinition(
   }
 
   CXXRecordDecl *Class = createLambdaClosureType(Intro.Range, MethodTyInfo,
-                                                 KnownDependent);
+                                                 KnownDependent, Intro.Default);
 
   CXXMethodDecl *Method = startLambdaDefinition(Class, Intro.Range,
                                                 MethodTyInfo, EndLoc, Params);
@@ -1155,7 +1163,6 @@ ExprResult Sema::ActOnLambdaExpr(SourceL
                                           CaptureInits, ArrayIndexVars, 
                                           ArrayIndexStarts, Body->getLocEnd(),
                                           ContainsUnexpandedParameterPack);
-  Class->setLambdaExpr(Lambda);
   // C++11 [expr.prim.lambda]p2:
   //   A lambda-expression shall not appear in an unevaluated operand
   //   (Clause 5).

Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=193223&r1=193222&r2=193223&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Tue Oct 22 21:59:27 2013
@@ -8352,7 +8352,9 @@ TreeTransform<Derived>::TransformLambdaE
   CXXRecordDecl *Class
     = getSema().createLambdaClosureType(E->getIntroducerRange(),
                                         NewCallOpTSI,
-                                        /*KnownDependent=*/false);
+                                        /*KnownDependent=*/false,
+                                        E->getCaptureDefault());
+
   getDerived().transformedLocalDecl(E->getLambdaClass(), Class);
 
   // Build the call operator.

Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=193223&r1=193222&r2=193223&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Tue Oct 22 21:59:27 2013
@@ -1226,6 +1226,8 @@ void ASTDeclReader::ReadCXXDefinitionDat
     CXXRecordDecl::LambdaDefinitionData &Lambda
       = static_cast<CXXRecordDecl::LambdaDefinitionData &>(Data);
     Lambda.Dependent = Record[Idx++];
+    Lambda.IsGenericLambda = Record[Idx++];
+    Lambda.CaptureDefault = Record[Idx++];
     Lambda.NumCaptures = Record[Idx++];
     Lambda.NumExplicitCaptures = Record[Idx++];
     Lambda.ManglingNumber = Record[Idx++];
@@ -1234,7 +1236,6 @@ void ASTDeclReader::ReadCXXDefinitionDat
       = (Capture*)Reader.Context.Allocate(sizeof(Capture)*Lambda.NumCaptures);
     Capture *ToCapture = Lambda.Captures;
     Lambda.MethodTyInfo = GetTypeSourceInfo(Record, Idx);
-    Lambda.TheLambdaExpr = cast<LambdaExpr>(Reader.ReadExpr(F));
     for (unsigned I = 0, N = Lambda.NumCaptures; I != N; ++I) {
       SourceLocation Loc = ReadSourceLocation(Record, Idx);
       bool IsImplicit = Record[Idx++];
@@ -1266,7 +1267,8 @@ ASTDeclReader::VisitCXXRecordDeclImpl(CX
     bool IsLambda = Record[Idx++];
     if (IsLambda)
       D->DefinitionData = new (C) CXXRecordDecl::LambdaDefinitionData(D, 0,
-                                                                      false);
+                                                                      false,
+                                                                      false, LCD_None);
     else
       D->DefinitionData = new (C) struct CXXRecordDecl::DefinitionData(D);
 

Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=193223&r1=193222&r2=193223&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriter.cpp Tue Oct 22 21:59:27 2013
@@ -5129,12 +5129,13 @@ void ASTWriter::AddCXXDefinitionData(con
   if (Data.IsLambda) {
     CXXRecordDecl::LambdaDefinitionData &Lambda = D->getLambdaData();
     Record.push_back(Lambda.Dependent);
+    Record.push_back(Lambda.IsGenericLambda);
+    Record.push_back(Lambda.CaptureDefault);
     Record.push_back(Lambda.NumCaptures);
     Record.push_back(Lambda.NumExplicitCaptures);
     Record.push_back(Lambda.ManglingNumber);
     AddDeclRef(Lambda.ContextDecl, Record);
     AddTypeSourceInfo(Lambda.MethodTyInfo, Record);
-    AddStmt(Lambda.TheLambdaExpr);
     for (unsigned I = 0, N = Lambda.NumCaptures; I != N; ++I) {
       LambdaExpr::Capture &Capture = Lambda.Captures[I];
       AddSourceLocation(Capture.getLocation(), Record);

Added: cfe/trunk/test/PCH/cxx1y-lambdas.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/cxx1y-lambdas.mm?rev=193223&view=auto
==============================================================================
--- cfe/trunk/test/PCH/cxx1y-lambdas.mm (added)
+++ cfe/trunk/test/PCH/cxx1y-lambdas.mm Tue Oct 22 21:59:27 2013
@@ -0,0 +1,58 @@
+// RUN: %clang_cc1 -pedantic-errors -fblocks -std=c++1y -emit-pch %s -o %t-cxx1y
+// RUN: %clang_cc1 -ast-print -pedantic-errors -fblocks -std=c++1y -include-pch %t-cxx1y  %s | FileCheck -check-prefix=CHECK-PRINT %s
+
+#ifndef HEADER_INCLUDED
+
+#define HEADER_INCLUDED
+template<typename T>
+T add_slowly(const T& x, const T &y) {
+  return [](auto z, int y = 0) { return z + y; }(5);
+};
+
+inline int add_int_slowly_twice(int x, int y) {
+  int i = add_slowly(x, y);
+  auto lambda = [](auto z) { return z + z; };
+  return i + lambda(y);
+}
+
+inline int sum_array(int n) {
+  auto lambda = [](auto N) -> int {
+    int sum = 0;
+    int array[5] = { 1, 2, 3, 4, 5};
+  
+    for (unsigned I = 0; I < N; ++I)
+      sum += array[N];
+    return sum;
+  };
+
+  return lambda(n);
+}
+
+inline int to_block_pointer(int n) {
+  auto lambda = [=](int m) { return n + m; };
+  int (^block)(int) = lambda;
+  return block(17);
+}
+
+template<typename T>
+int init_capture(T t) {
+  return [&, x(t)] { return sizeof(x); };
+}
+
+#else
+
+// CHECK-PRINT: T add_slowly
+// CHECK-PRINT: return []
+template float add_slowly(const float&, const float&);
+
+int add(int x, int y) {
+  return add_int_slowly_twice(x, y) + sum_array(4) + to_block_pointer(5);
+}
+
+// CHECK-PRINT: inline int add_int_slowly_twice 
+// CHECK-PRINT: lambda = [] ($auto-0-0 z
+
+// CHECK-PRINT: init_capture
+// CHECK-PRINT: [&, x( t )]
+
+#endif





More information about the cfe-commits mailing list