r181101 - Implement template support for CapturedStmt

Wei Pan wei.pan at intel.com
Fri May 3 20:59:07 PDT 2013


Author: wpan
Date: Fri May  3 22:59:06 2013
New Revision: 181101

URL: http://llvm.org/viewvc/llvm-project?rev=181101&view=rev
Log:
Implement template support for CapturedStmt

- Sema tests added and CodeGen tests are pending

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


Modified:
    cfe/trunk/include/clang/AST/Stmt.h
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/AST/Stmt.cpp
    cfe/trunk/lib/Sema/SemaStmt.cpp
    cfe/trunk/lib/Sema/TreeTransform.h
    cfe/trunk/lib/Serialization/ASTReaderStmt.cpp
    cfe/trunk/lib/Serialization/ASTWriterStmt.cpp
    cfe/trunk/test/SemaCXX/captured-statements.cpp

Modified: cfe/trunk/include/clang/AST/Stmt.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Stmt.h?rev=181101&r1=181100&r2=181101&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Stmt.h (original)
+++ cfe/trunk/include/clang/AST/Stmt.h Fri May  3 22:59:06 2013
@@ -16,6 +16,7 @@
 
 #include "clang/AST/DeclGroup.h"
 #include "clang/AST/StmtIterator.h"
+#include "clang/Basic/CapturedStmt.h"
 #include "clang/Basic/IdentifierTable.h"
 #include "clang/Basic/LLVM.h"
 #include "clang/Basic/SourceLocation.h"
@@ -1982,16 +1983,16 @@ private:
   /// \brief The number of variable captured, including 'this'.
   unsigned NumCaptures;
 
-  /// \brief The implicit outlined function.
-  CapturedDecl *TheCapturedDecl;
+  /// \brief The pointer part is the implicit the outlined function and the 
+  /// int part is the captured region kind, 'CR_Default' etc.
+  llvm::PointerIntPair<CapturedDecl *, 1, CapturedRegionKind> CapDeclAndKind;
 
   /// \brief The record for captured variables, a RecordDecl or CXXRecordDecl.
   RecordDecl *TheRecordDecl;
 
   /// \brief Construct a captured statement.
-  CapturedStmt(Stmt *S, ArrayRef<Capture> Captures,
-               ArrayRef<Expr *> CaptureInits,
-               CapturedDecl *CD, RecordDecl *RD);
+  CapturedStmt(Stmt *S, CapturedRegionKind Kind, ArrayRef<Capture> Captures,
+               ArrayRef<Expr *> CaptureInits, CapturedDecl *CD, RecordDecl *RD);
 
   /// \brief Construct an empty captured statement.
   CapturedStmt(EmptyShell Empty, unsigned NumCaptures);
@@ -2006,6 +2007,7 @@ private:
 
 public:
   static CapturedStmt *Create(ASTContext &Context, Stmt *S,
+                              CapturedRegionKind Kind,
                               ArrayRef<Capture> Captures,
                               ArrayRef<Expr *> CaptureInits,
                               CapturedDecl *CD, RecordDecl *RD);
@@ -2020,11 +2022,36 @@ public:
   }
 
   /// \brief Retrieve the outlined function declaration.
-  CapturedDecl *getCapturedDecl() const { return TheCapturedDecl; }
+  CapturedDecl *getCapturedDecl() { return CapDeclAndKind.getPointer(); }
+  const CapturedDecl *getCapturedDecl() const {
+    return const_cast<CapturedStmt *>(this)->getCapturedDecl();
+  }
+
+  /// \brief Set the outlined function declaration.
+  void setCapturedDecl(CapturedDecl *D) {
+    assert(D && "null CapturedDecl");
+    CapDeclAndKind.setPointer(D);
+  }
+
+  /// \brief Retrieve the captured region kind.
+  CapturedRegionKind getCapturedRegionKind() const {
+    return CapDeclAndKind.getInt();
+  }
+
+  /// \brief Set the captured region kind.
+  void setCapturedRegionKind(CapturedRegionKind Kind) {
+    CapDeclAndKind.setInt(Kind);
+  }
 
   /// \brief Retrieve the record declaration for captured variables.
   const RecordDecl *getCapturedRecordDecl() const { return TheRecordDecl; }
 
+  /// \brief Set the record declaration for captured variables.
+  void setCapturedRecordDecl(RecordDecl *D) {
+    assert(D && "null RecordDecl");
+    TheRecordDecl = D;
+  }
+
   /// \brief True if this variable has been captured.
   bool capturesVariable(const VarDecl *Var) const;
 

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=181101&r1=181100&r2=181101&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Fri May  3 22:59:06 2013
@@ -2798,7 +2798,7 @@ public:
   void ActOnCapturedRegionStart(SourceLocation Loc, Scope *CurScope,
                                 CapturedRegionKind Kind, unsigned NumParams);
   StmtResult ActOnCapturedRegionEnd(Stmt *S);
-  void ActOnCapturedRegionError(bool IsInstantiation = false);
+  void ActOnCapturedRegionError();
   RecordDecl *CreateCapturedStmtRecordDecl(CapturedDecl *&CD,
                                            SourceLocation Loc,
                                            unsigned NumParams);

Modified: cfe/trunk/lib/AST/Stmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Stmt.cpp?rev=181101&r1=181100&r2=181101&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Stmt.cpp (original)
+++ cfe/trunk/lib/AST/Stmt.cpp Fri May  3 22:59:06 2013
@@ -1049,12 +1049,13 @@ CapturedStmt::Capture *CapturedStmt::get
       + FirstCaptureOffset);
 }
 
-CapturedStmt::CapturedStmt(Stmt *S, ArrayRef<Capture> Captures,
+CapturedStmt::CapturedStmt(Stmt *S, CapturedRegionKind Kind,
+                           ArrayRef<Capture> Captures,
                            ArrayRef<Expr *> CaptureInits,
                            CapturedDecl *CD,
                            RecordDecl *RD)
   : Stmt(CapturedStmtClass), NumCaptures(Captures.size()),
-    TheCapturedDecl(CD), TheRecordDecl(RD) {
+    CapDeclAndKind(CD, Kind), TheRecordDecl(RD) {
   assert( S && "null captured statement");
   assert(CD && "null captured declaration for captured statement");
   assert(RD && "null record declaration for captured statement");
@@ -1074,11 +1075,12 @@ CapturedStmt::CapturedStmt(Stmt *S, Arra
 
 CapturedStmt::CapturedStmt(EmptyShell Empty, unsigned NumCaptures)
   : Stmt(CapturedStmtClass, Empty), NumCaptures(NumCaptures),
-    TheCapturedDecl(0), TheRecordDecl(0) {
+    CapDeclAndKind(0, CR_Default), TheRecordDecl(0) {
   getStoredStmts()[NumCaptures] = 0;
 }
 
 CapturedStmt *CapturedStmt::Create(ASTContext &Context, Stmt *S,
+                                   CapturedRegionKind Kind,
                                    ArrayRef<Capture> Captures,
                                    ArrayRef<Expr *> CaptureInits,
                                    CapturedDecl *CD,
@@ -1102,7 +1104,7 @@ CapturedStmt *CapturedStmt::Create(ASTCo
   }
 
   void *Mem = Context.Allocate(Size);
-  return new (Mem) CapturedStmt(S, Captures, CaptureInits, CD, RD);
+  return new (Mem) CapturedStmt(S, Kind, Captures, CaptureInits, CD, RD);
 }
 
 CapturedStmt *CapturedStmt::CreateDeserialized(ASTContext &Context,

Modified: cfe/trunk/lib/Sema/SemaStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmt.cpp?rev=181101&r1=181100&r2=181101&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaStmt.cpp (original)
+++ cfe/trunk/lib/Sema/SemaStmt.cpp Fri May  3 22:59:06 2013
@@ -2981,7 +2981,8 @@ static void buildCapturedStmtCaptureList
 }
 
 void Sema::ActOnCapturedRegionStart(SourceLocation Loc, Scope *CurScope,
-                                    CapturedRegionKind Kind, unsigned NumParams) {
+                                    CapturedRegionKind Kind,
+                                    unsigned NumParams) {
   CapturedDecl *CD = 0;
   RecordDecl *RD = CreateCapturedStmtRecordDecl(CD, Loc, NumParams);
 
@@ -2996,13 +2997,10 @@ void Sema::ActOnCapturedRegionStart(Sour
   PushExpressionEvaluationContext(PotentiallyEvaluated);
 }
 
-void Sema::ActOnCapturedRegionError(bool IsInstantiation) {
+void Sema::ActOnCapturedRegionError() {
   DiscardCleanupsInEvaluationContext();
   PopExpressionEvaluationContext();
 
-  if (!IsInstantiation)
-    PopDeclContext();
-
   CapturedRegionScopeInfo *RSI = getCurCapturedRegion();
   RecordDecl *Record = RSI->TheRecordDecl;
   Record->setInvalidDecl();
@@ -3014,6 +3012,7 @@ void Sema::ActOnCapturedRegionError(bool
   ActOnFields(/*Scope=*/0, Record->getLocation(), Record, Fields,
               SourceLocation(), SourceLocation(), /*AttributeList=*/0);
 
+  PopDeclContext();
   PopFunctionScopeInfo();
 }
 
@@ -3027,12 +3026,16 @@ StmtResult Sema::ActOnCapturedRegionEnd(
   CapturedDecl *CD = RSI->TheCapturedDecl;
   RecordDecl *RD = RSI->TheRecordDecl;
 
-  CapturedStmt *Res = CapturedStmt::Create(getASTContext(), S, Captures,
+  CapturedStmt *Res = CapturedStmt::Create(getASTContext(), S,
+                                           RSI->CapRegionKind, Captures,
                                            CaptureInits, CD, RD);
 
   CD->setBody(Res->getCapturedStmt());
   RD->completeDefinition();
 
+  DiscardCleanupsInEvaluationContext();
+  PopExpressionEvaluationContext();
+
   PopDeclContext();
   PopFunctionScopeInfo();
 

Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=181101&r1=181100&r2=181101&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Fri May  3 22:59:06 2013
@@ -9449,7 +9449,18 @@ TreeTransform<Derived>::RebuildCXXPseudo
 template<typename Derived>
 StmtResult
 TreeTransform<Derived>::TransformCapturedStmt(CapturedStmt *S) {
-  llvm_unreachable("not implement yet");
+  SourceLocation Loc = S->getLocStart();
+  unsigned NumParams = S->getCapturedDecl()->getNumParams();
+  getSema().ActOnCapturedRegionStart(Loc, /*CurScope*/0,
+                                     S->getCapturedRegionKind(), NumParams);
+  StmtResult Body = getDerived().TransformStmt(S->getCapturedStmt());
+
+  if (Body.isInvalid()) {
+    getSema().ActOnCapturedRegionError();
+    return StmtError();
+  }
+
+  return getSema().ActOnCapturedRegionEnd(Body.take());
 }
 
 } // end namespace clang

Modified: cfe/trunk/lib/Serialization/ASTReaderStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderStmt.cpp?rev=181101&r1=181100&r2=181101&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReaderStmt.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReaderStmt.cpp Fri May  3 22:59:06 2013
@@ -382,8 +382,9 @@ void ASTStmtReader::VisitMSAsmStmt(MSAsm
 
 void ASTStmtReader::VisitCapturedStmt(CapturedStmt *S) {
   VisitStmt(S);
-  S->TheCapturedDecl = ReadDeclAs<CapturedDecl>(Record, Idx);
-  S->TheRecordDecl = ReadDeclAs<RecordDecl>(Record, Idx);
+  S->setCapturedDecl(ReadDeclAs<CapturedDecl>(Record, Idx));
+  S->setCapturedRegionKind(static_cast<CapturedRegionKind>(Record[Idx++]));
+  S->setCapturedRecordDecl(ReadDeclAs<RecordDecl>(Record, Idx));
 
   // Capture inits
   for (CapturedStmt::capture_init_iterator I = S->capture_init_begin(),
@@ -393,7 +394,7 @@ void ASTStmtReader::VisitCapturedStmt(Ca
 
   // Body
   S->setCapturedStmt(Reader.ReadSubStmt());
-  S->TheCapturedDecl->setBody(S->getCapturedStmt());
+  S->getCapturedDecl()->setBody(S->getCapturedStmt());
 
   // Captures
   for (CapturedStmt::capture_iterator I = S->capture_begin(),

Modified: cfe/trunk/lib/Serialization/ASTWriterStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterStmt.cpp?rev=181101&r1=181100&r2=181101&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriterStmt.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriterStmt.cpp Fri May  3 22:59:06 2013
@@ -290,7 +290,10 @@ void ASTStmtWriter::VisitCapturedStmt(Ca
   // NumCaptures
   Record.push_back(std::distance(S->capture_begin(), S->capture_end()));
 
+  // CapturedDecl and captured region kind
   Writer.AddDeclRef(S->getCapturedDecl(), Record);
+  Record.push_back(S->getCapturedRegionKind());
+
   Writer.AddDeclRef(S->getCapturedRecordDecl(), Record);
 
   // Capture inits

Modified: cfe/trunk/test/SemaCXX/captured-statements.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/captured-statements.cpp?rev=181101&r1=181100&r2=181101&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/captured-statements.cpp (original)
+++ cfe/trunk/test/SemaCXX/captured-statements.cpp Fri May  3 22:59:06 2013
@@ -50,3 +50,117 @@ class test_this_capture {
     { b(); }        // OK
   }
 };
+
+template <typename T>
+void template_capture_var() {
+  T x; // expected-error{{declaration of reference variable 'x' requires an initializer}}
+  #pragma clang _debug captured
+  {
+    (void)x;
+  }
+}
+
+template <typename T>
+class Val {
+  T v;
+public:
+  void set(const T &v0) {
+    #pragma clang __debug captured
+    {
+      v = v0;
+    }
+  }
+};
+
+void test_capture_var() {
+  template_capture_var<int>(); // OK
+  template_capture_var<int&>(); // expected-note{{in instantiation of function template specialization 'template_capture_var<int &>' requested here}}
+
+  Val<float> Obj;
+  Obj.set(0.0f); // OK
+}
+
+template <typename S, typename T>
+S template_capture_var(S x, T y) {
+  #pragma clang _debug captured
+  {
+    x++;
+    y++;  // expected-error{{read-only variable is not assignable}}
+  }
+
+  return x;
+}
+
+// Check if can recover from a template error.
+void test_capture_var_error() {
+  template_capture_var<int, int>(0, 1); // OK
+  template_capture_var<int, const int>(0, 1); // expected-note{{in instantiation of function template specialization 'template_capture_var<int, const int>' requested here}}
+  template_capture_var<int, int>(0, 1); // OK
+}
+
+template <typename T>
+void template_capture_in_lambda() {
+  T x, y;
+  [=, &y]() {
+    #pragma clang __debug captured
+    {
+      y += x;
+    }
+  }();
+}
+
+void test_lambda() {
+  template_capture_in_lambda<int>(); // OK
+}
+
+struct Foo {
+  void foo() { }
+  static void bar() { }
+};
+
+template <typename T>
+void template_capture_func(T &t) {
+  #pragma clang __debug captured
+  {
+    t.foo();
+  }
+
+  #pragma clang __debug captured
+  {
+    T::bar();
+  }
+}
+
+void test_template_capture_func() {
+  Foo Obj;
+  template_capture_func(Obj);
+}
+
+template <typename T>
+T captured_sum(const T &a, const T &b) {
+  T result;
+
+  #pragma clang __debug captured
+  {
+    result = a + b;
+  }
+
+  return result;
+}
+
+template <typename T, typename... Args>
+T captured_sum(const T &a, const Args&... args) {
+  T result;
+
+  #pragma clang __debug captured
+  {
+    result = a + captured_sum(args...);
+  }
+
+  return result;
+}
+
+void test_capture_variadic() {
+  (void)captured_sum(1, 2, 3); // OK
+  (void)captured_sum(1, 2, 3, 4, 5); // OK
+}





More information about the cfe-commits mailing list