diff options
-rw-r--r-- | include/clang/AST/Expr.h | 8 | ||||
-rw-r--r-- | lib/AST/Expr.cpp | 12 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateVariadic.cpp | 11 | ||||
-rw-r--r-- | lib/Sema/TreeTransform.h | 38 | ||||
-rw-r--r-- | test/CXX/temp/temp.decls/temp.variadic/ext-blocks.cpp | 39 |
5 files changed, 89 insertions, 19 deletions
diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index 3bcbf3661a..46fda21fc0 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -3572,15 +3572,9 @@ class BlockDeclRefExpr : public Expr { 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. diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 4afed433a3..9dc790256e 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -2932,6 +2932,18 @@ Stmt::child_iterator ObjCMessageExpr::child_end() { } // 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(); } diff --git a/lib/Sema/SemaTemplateVariadic.cpp b/lib/Sema/SemaTemplateVariadic.cpp index 38a777efb1..3f76d9f6e3 100644 --- a/lib/Sema/SemaTemplateVariadic.cpp +++ b/lib/Sema/SemaTemplateVariadic.cpp @@ -64,7 +64,7 @@ namespace { 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 @@ namespace { 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 diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index ebc34d0f35..1cb24e70bf 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -7122,16 +7122,13 @@ TreeTransform<Derived>::TransformBlockExpr(BlockExpr *E) { 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 @@ TreeTransform<Derived>::TransformBlockExpr(BlockExpr *E) { 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 @@ TreeTransform<Derived>::TransformBlockExpr(BlockExpr *E) { // 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()) diff --git a/test/CXX/temp/temp.decls/temp.variadic/ext-blocks.cpp b/test/CXX/temp/temp.decls/temp.variadic/ext-blocks.cpp new file mode 100644 index 0000000000..62cf4298f7 --- /dev/null +++ b/test/CXX/temp/temp.decls/temp.variadic/ext-blocks.cpp @@ -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); |