[cfe-commits] r123849 - in /cfe/trunk: include/clang/AST/Expr.h lib/AST/Expr.cpp lib/Sema/SemaTemplateVariadic.cpp lib/Sema/TreeTransform.h test/CXX/temp/temp.decls/temp.variadic/ext-blocks.cpp

Douglas Gregor dgregor at apple.com
Wed Jan 19 13:32:01 PST 2011


Author: dgregor
Date: Wed Jan 19 15:32:01 2011
New Revision: 123849

URL: http://llvm.org/viewvc/llvm-project?rev=123849&view=rev
Log:
Implement basic support for the use of variadic templates and blocks
together. In particular: 
  - Handle the use of captured parameter pack names within blocks
  (BlockDeclRefExpr understands parameter packs now)
  - Handle the declaration and expansion of parameter packs within a block's
  parameter list, e.g., ^(Args ...args) { ... })
  - Handle instantiation of blocks where the return type was not
  explicitly specified. (unrelated, but necessary for my tests).

Together, these fixes should make blocks and variadic templates work
reasonably well together. Note that BlockDeclRefExpr is still broken
w.r.t. its computation of type and value dependence, which will still
cause problems for blocks in templates.


Added:
    cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/ext-blocks.cpp   (with props)
Modified:
    cfe/trunk/include/clang/AST/Expr.h
    cfe/trunk/lib/AST/Expr.cpp
    cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp
    cfe/trunk/lib/Sema/TreeTransform.h

Modified: cfe/trunk/include/clang/AST/Expr.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Expr.h?rev=123849&r1=123848&r2=123849&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Expr.h (original)
+++ cfe/trunk/include/clang/AST/Expr.h Wed Jan 19 15:32:01 2011
@@ -3572,15 +3572,9 @@
   bool ConstQualAdded : 1;
   Stmt *CopyConstructorVal;
 public:
-  // FIXME: Fix type/value dependence!
-  // FIXME: Variadic templates.
   BlockDeclRefExpr(ValueDecl *d, QualType t, ExprValueKind VK,
                    SourceLocation l, bool ByRef, bool constAdded = false,
-                   Stmt *copyConstructorVal = 0)
-    : Expr(BlockDeclRefExprClass, t, VK, OK_Ordinary,
-           (!t.isNull() && t->isDependentType()), false, false),
-    D(d), Loc(l), IsByRef(ByRef),
-    ConstQualAdded(constAdded),  CopyConstructorVal(copyConstructorVal) {}
+                   Stmt *copyConstructorVal = 0);
 
   // \brief Build an empty reference to a declared variable in a
   // block.

Modified: cfe/trunk/lib/AST/Expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Expr.cpp?rev=123849&r1=123848&r2=123849&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Expr.cpp (original)
+++ cfe/trunk/lib/AST/Expr.cpp Wed Jan 19 15:32:01 2011
@@ -2932,6 +2932,18 @@
 }
 
 // Blocks
+BlockDeclRefExpr::BlockDeclRefExpr(ValueDecl *d, QualType t, ExprValueKind VK,
+                                   SourceLocation l, bool ByRef, 
+                                   bool constAdded, Stmt *copyConstructorVal)
+  : Expr(BlockDeclRefExprClass, t, VK, OK_Ordinary,
+         (!t.isNull() && t->isDependentType()), false,
+         d->isParameterPack()),
+    D(d), Loc(l), IsByRef(ByRef),
+    ConstQualAdded(constAdded),  CopyConstructorVal(copyConstructorVal) 
+{
+  // FIXME: Compute type/value dependence.
+}
+
 Stmt::child_iterator BlockExpr::child_begin() { return child_iterator(); }
 Stmt::child_iterator BlockExpr::child_end() { return child_iterator(); }
 

Modified: cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp?rev=123849&r1=123848&r2=123849&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp Wed Jan 19 15:32:01 2011
@@ -64,7 +64,7 @@
       return true;
     }
 
-    /// \brief Record occurrences of (FIXME: function and) non-type template
+    /// \brief Record occurrences of function and non-type template
     /// parameter packs in an expression.
     bool VisitDeclRefExpr(DeclRefExpr *E) {
       if (E->getDecl()->isParameterPack())
@@ -73,6 +73,15 @@
       return true;
     }
     
+    // \brief Record occurrences of function and non-type template parameter
+    // packs in a block-captured expression.
+    bool VisitBlockDeclRefExpr(BlockDeclRefExpr *E) {
+      if (E->getDecl()->isParameterPack())
+        Unexpanded.push_back(std::make_pair(E->getDecl(), E->getLocation()));
+      
+      return true;
+    }
+    
     /// \brief Record occurrences of template template parameter packs.
     bool TraverseTemplateName(TemplateName Template) {
       if (TemplateTemplateParmDecl *TTP 

Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=123849&r1=123848&r2=123849&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Wed Jan 19 15:32:01 2011
@@ -7122,16 +7122,13 @@
   llvm::SmallVector<QualType, 4> ParamTypes;
   
   // Parameter substitution.
-  // FIXME: Variadic templates
-  const BlockDecl *BD = E->getBlockDecl();
-  for (BlockDecl::param_const_iterator P = BD->param_begin(),
-       EN = BD->param_end(); P != EN; ++P) {
-    ParmVarDecl *OldParm = (*P);
-    ParmVarDecl *NewParm = getDerived().TransformFunctionTypeParam(OldParm,
-                                                   llvm::Optional<unsigned>());
-    Params.push_back(NewParm);
-    ParamTypes.push_back(NewParm->getType());
-  }
+  BlockDecl *BD = E->getBlockDecl();
+  if (getDerived().TransformFunctionTypeParams(E->getLocStart(), 
+                                               BD->param_begin(),
+                                               BD->param_size(), 0, ParamTypes,
+                                               &Params))
+    return true;
+  
   
   const FunctionType *BExprFunctionType = E->getFunctionType();
   QualType BExprResultType = BExprFunctionType->getResultType();
@@ -7141,6 +7138,19 @@
     else if (BExprResultType != SemaRef.Context.DependentTy)
       CurBlock->ReturnType = getDerived().TransformType(BExprResultType);
   }
+  
+  // If the return type has not been determined yet, leave it as a dependent
+  // type; it'll get set when we process the body.
+  if (CurBlock->ReturnType.isNull())
+    CurBlock->ReturnType = getSema().Context.DependentTy;
+
+  // Don't allow returning a objc interface by value.
+  if (CurBlock->ReturnType->isObjCObjectType()) {
+    getSema().Diag(E->getLocStart(), 
+                   diag::err_object_cannot_be_passed_returned_by_value) 
+      << 0 << CurBlock->ReturnType;
+    return ExprError();
+  }
 
   QualType FunctionType = getDerived().RebuildFunctionProtoType(
                                                         CurBlock->ReturnType,
@@ -7154,7 +7164,13 @@
   // Set the parameters on the block decl.
   if (!Params.empty())
     CurBlock->TheDecl->setParams(Params.data(), Params.size());
-    
+  
+  // If the return type wasn't explicitly set, it will have been marked as a 
+  // dependent type (DependentTy); clear out the return type setting so 
+  // we will deduce the return type when type-checking the block's body.
+  if (CurBlock->ReturnType == getSema().Context.DependentTy)
+    CurBlock->ReturnType = QualType();
+  
   // Transform the body
   StmtResult Body = getDerived().TransformStmt(E->getBody());
   if (Body.isInvalid())

Added: cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/ext-blocks.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/ext-blocks.cpp?rev=123849&view=auto
==============================================================================
--- cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/ext-blocks.cpp (added)
+++ cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/ext-blocks.cpp Wed Jan 19 15:32:01 2011
@@ -0,0 +1,39 @@
+// RUN: %clang_cc1 -std=c++0x -fblocks -fsyntax-only -verify %s
+
+// Tests the use of blocks with variadic templates.
+template<typename ...Args>
+int f0(Args ...args) {
+  return ^ {
+    return sizeof...(Args);
+  }() + ^ {
+    return sizeof...(args);
+  }();
+}
+
+template<typename ...Args>
+int f1(Args ...args) {
+  return ^ {
+    return f0(args...);
+  }();
+}
+
+template int f0(int, float, double);
+template int f1(const char*, int, float, double);
+
+template<typename ...Args>
+int f2(Args ...args) {
+  return ^(Args ...block_args) {
+    return f1(block_args...);
+  }(args + 0 ...);
+}
+
+template int f2(const char*, int, float, double);
+
+template<typename ...Args>
+int f3(Args ...args) {
+  return ^(Args *...block_args) {
+    return f1(block_args...);
+  }(&args...);
+}
+
+template int f3(const char*, int, float, double);

Propchange: cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/ext-blocks.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/ext-blocks.cpp
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/ext-blocks.cpp
------------------------------------------------------------------------------
    svn:mime-type = text/plain





More information about the cfe-commits mailing list